From patchwork Fri May 7 04:06:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475316 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxjn1w2xz9sPf for ; Fri, 7 May 2021 14:07:25 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 75C9683D0C; Fri, 7 May 2021 04:07:16 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id y848lFbTgpxo; Fri, 7 May 2021 04:07:15 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id C26AB83CD9; Fri, 7 May 2021 04:07:14 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 8ABC2C000F; Fri, 7 May 2021 04:07:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 957F2C0022 for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 63B50402E8 for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ag4NRBU3PmzB for ; Fri, 7 May 2021 04:07:09 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 6E661402D3 for ; Fri, 7 May 2021 04:07:09 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id E9F76C0007; Fri, 7 May 2021 04:07:06 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:33 -0700 Message-Id: <20210507040659.26830-2-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 01/27] ovn-northd-ddlog: Fix two memory leaks. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" I get a clean report from Address Sanitizer now. Signed-off-by: Ben Pfaff --- northd/ovn-northd-ddlog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/northd/ovn-northd-ddlog.c b/northd/ovn-northd-ddlog.c index b7d2c8a5ef8d..ca1ab325448c 100644 --- a/northd/ovn-northd-ddlog.c +++ b/northd/ovn-northd-ddlog.c @@ -336,6 +336,7 @@ ddlog_commit(ddlog_prog ddlog, ddlog_delta *delta) /* Merge changes into `delta`. */ ddlog_delta_union(delta, new_delta); + ddlog_free_delta(new_delta); return 0; } @@ -1213,6 +1214,7 @@ main(int argc, char *argv[]) char *ovn_internal_version = ovn_get_internal_version(); VLOG_INFO("OVN internal version is : [%s]", ovn_internal_version); + free(ovn_internal_version); daemonize_complete(); From patchwork Fri May 7 04:06:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475314 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxjj6TRyz9sPf for ; Fri, 7 May 2021 14:07:21 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 73D7D83CE4; Fri, 7 May 2021 04:07:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id px70QDNKtaNb; Fri, 7 May 2021 04:07:14 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id A884083CB9; Fri, 7 May 2021 04:07:13 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id DD9C2C0022; Fri, 7 May 2021 04:07:12 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 81A88C000D for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5FC5E83CB1 for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id u_VPafaN74n3 for ; Fri, 7 May 2021 04:07:11 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id BAC3283BB8 for ; Fri, 7 May 2021 04:07:10 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 5340AC0009; Fri, 7 May 2021 04:07:08 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:34 -0700 Message-Id: <20210507040659.26830-3-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 02/27] ovn-nbctl: Fix memory leak in client mode. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This isn't notable, since this commit frees it just before exiting, but it cleans up the Address Sanitizer report. Signed-off-by: Ben Pfaff --- utilities/ovn-nbctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index 042c210020b8..e3af0be926da 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -7100,5 +7100,9 @@ nbctl_client(const char *socket_name, free(cmd_result); free(cmd_error); jsonrpc_close(client); + for (int i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); exit(exit_status); } From patchwork Fri May 7 04:06:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475315 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxjk4pMXz9sXS for ; Fri, 7 May 2021 14:07:22 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 54791402F3; Fri, 7 May 2021 04:07:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yomYoYJSCBzW; Fri, 7 May 2021 04:07:17 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTP id 7F692402F4; Fri, 7 May 2021 04:07:16 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5D111C0022; Fri, 7 May 2021 04:07:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id EF7D0C0001 for ; Fri, 7 May 2021 04:07:14 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id D9CE1402F2 for ; Fri, 7 May 2021 04:07:14 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9qNZevz_IM7l for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 7C3E7402D3 for ; Fri, 7 May 2021 04:07:12 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id C2FD6C0004; Fri, 7 May 2021 04:07:09 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:35 -0700 Message-Id: <20210507040659.26830-4-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 03/27] ovn-nbctl: Improve manpage. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This rearranges the manpage into a more logical order, documents some options that weren't documented, adds some sections such as Environment and Exit Status that a manpage should have, puts the headings at reasonable levels instead of all at the top level, and adds a little more explanatory text in a few places. Signed-off-by: Ben Pfaff --- utilities/ovn-nbctl.8.xml | 670 ++++++++++++++++++++++---------------- 1 file changed, 392 insertions(+), 278 deletions(-) diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 03d47dba5b72..39f9381fdaae 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -7,9 +7,327 @@

ovn-nbctl [options] command [arg...]

Description

-

This utility can be used to manage the OVN northbound database.

-

General Commands

+

+ The ovn-nbctl program configures the + OVN_Northbound database by providing a high-level interface + to its configuration database. See ovn-nb(5) for + comprehensive documentation of the database schema. +

+ +

+ ovn-nbctl connects to an ovsdb-server process + that maintains an OVN_Northbound configuration database. Using this + connection, it queries and possibly applies changes to the database, + depending on the supplied commands. +

+ +

+ ovn-nbctl can perform any number of commands in a single + run, implemented as a single atomic transaction against the database. +

+ +

+ The ovn-nbctl command line begins with global options (see + OPTIONS below for details). The global options are followed + by one or more commands. Each command should begin with -- + by itself as a command-line argument, to separate it from the following + commands. (The -- before the first command is optional.) + The command itself starts with command-specific options, if any, followed + by the command name and any arguments. +

+ +

Daemon Mode

+ +

+ When it is invoked in the most ordinary way, ovn-nbctl + connects to an OVSDB server that hosts the northbound database, retrieves + a partial copy of the database that is complete enough to do its work, + sends a transaction request to the server, and receives and processes the + server's reply. In common interactive use, this is fine, but if the + database is large, the step in which ovn-nbctl retrieves a + partial copy of the database can take a long time, which yields poor + performance overall. +

+ +

+ To improve performance in such a case, ovn-nbctl offers a + "daemon mode," in which the user first starts ovn-nbctl + running in the background and afterward uses the daemon to execute + operations. Over several ovn-nbctl command invocations, + this performs better overall because it retrieves a copy of the database + only once at the beginning, not once per program run. +

+ +

+ Use the --detach option to start an ovn-nbctl + daemon. With this option, ovn-nbctl prints the name of a + control socket to stdout. The client should save this name in + environment variable OVN_NB_DAEMON. Under the Bourne shell + this might be done like this: +

+ +
+      export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
+    
+ +

+ When OVN_NB_DAEMON is set, ovn-nbctl + automatically and transparently uses the daemon to execute its commands. +

+ +

+ When the daemon is no longer needed, kill it and unset the environment + variable, e.g.: +

+ +
+      kill $(cat $OVN_RUNDIR/ovn-nbctl.pid)
+      unset OVN_NB_DAEMON
+    
+ +

+ When using daemon mode, an alternative to the OVN_NB_DAEMON + environment variable is to specify a path for the Unix socket. When + starting the ovn-nbctl daemon, specify the -u option with a + full path to the location of the socket file. Here is an exmple: +

+ +
+      ovn-nbctl --detach -u /tmp/mysock.ctl
+    
+ +

+ Then to connect to the running daemon, use the -u option + with the full path to the socket created when the daemon was started: +

+ +
+      ovn-nbctl -u /tmp/mysock.ctl show
+    
+ +

+ Daemon mode is experimental. +

+ +

Daemon Commands

+ +

+ Daemon mode is internally implemented using the same mechanism used by + ovs-appctl. One may also use ovs-appctl + directly with the following commands: +

+ +
+
+ run [options] command + [arg...] [-- [options] + command [arg...] ...] +
+
+ Instructs the daemon process to run one or more ovn-nbctl + commands described above and reply with the results of running these + commands. Accepts the --no-wait, --wait, + --timeout, --dry-run, --oneline, + and the options described under Table Formatting Options + in addition to the the command-specific options. +
+ +
exit
+
Causes ovn-nbctl to gracefully terminate.
+
+ +

Options

+ +

+ The options listed below affect the behavior of ovn-nbctl as + a whole. Some individual commands also accept their own options, which + are given just before the command name. If the first command on the + command line has options, then those options must be separated from the + global options by --. +

+ +

+ ovn-nbctl also accepts options from the + OVN_NBCTL_OPTIONS environment variable, in the same format as + on the command line. Options from the command line override those in the + environment. +

+ +
+
--no-wait | --wait=none
+
--wait=sb
+
--wait=hv
+ +
+

+ These options control whether and how ovn-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-nbctl invocation. +

+ +

+ By default, or if --no-wait or --wait=none, + ovn-nbctl exits immediately after confirming that + changes have been committed to the northbound database, without + waiting. +

+ +

+ With --wait=sb, before ovn-nbctl exits, it + waits for ovn-northd to bring the southbound database + up-to-date with the northbound database updates. +

+ +

+ With --wait=hv, before ovn-nbctl exits, it + additionally waits for all OVN chassis (hypervisors and gateways) to + become up-to-date with the northbound database updates. (This can + become an indefinite wait if any chassis is malfunctioning.) +

+ +

+ Ordinarily, --wait=sb or --wait=hv only + waits for changes by the current ovn-nbctl invocation to + take effect. This means that, if none of the commands supplied to + ovn-nbctl change the database, then the command does not + wait at all. Use the sync command to override this + behavior. +

+
+ +
--db database
+
+ The OVSDB database remote to contact. If the OVN_NB_DB + environment variable is set, its value is used as the default. + Otherwise, the default is unix:@RUNDIR@/ovnnb_db.sock, but + this default is unlikely to be useful outside of single-machine OVN + test environments. +
+ +
--leader-only
+
--no-leader-only
+
+ By default, or with --leader-only, when the database + server is a clustered database, ovn-nbctl will avoid + servers other than the cluster leader. This ensures that any data that + ovn-nbctl reads and reports is up-to-date. With + --no-leader-only, ovn-nbctl will use any + server in the cluster, which means that for read-only transactions it + can report and act on stale data (transactions that modify the database + are always serialized even with --no-leader-only). Refer + to Understanding Cluster Consistency in + ovsdb(7) for more information. +
+ +
--shuffle-remotes
+
--no-shuffle-remotes
+
+ By default, or with --shuffle-remotes, when there are + multiple remotes specified in the OVSDB connection string specified by + --db or the OVN_NB_DB environment variable, the + order of the remotes will be shuffled before the client tries to + connect. The remotes will be shuffled only once to a new order before + the first connection attempt. The following retries, if any, will + follow the same new order. The default behavior is to make sure + clients of a clustered database can distribute evenly to all memembers + of the cluster. With --no-shuffle-remotes, + ovn-nbctl will use the original order specified in the + connection string to connect. This allows user to specify the + preferred order, which is particularly useful for testing. +
+ +
--no-syslog
+
+

+ By default, ovn-nbctl logs its arguments and the details + of any changes that it makes to the system log. This option disables + this logging. +

+ +

+ This option is equivalent to + --verbose=nbctl:syslog:warn. +

+
+ +
--oneline
+
+ Modifies the output format so that the output for each command is + printed on a single line. New-line characters that would otherwise + separate lines are printed as \fB\\n\fR, and any instances of \fB\\\fR + that would otherwise appear in the output are doubled. Prints a blank + line for each command that has no output. This option does not affect + the formatting of output from the list or + find commands; see Table Formatting Options + below. +
+ +
--dry-run
+
+ Prevents ovn-nbctl from actually modifying the database. +
+ +
-t secs
+
--timeout=secs
+
+ By default, or with a secs of 0, + ovn-nbctl waits forever for a response from the database. + This option limits runtime to approximately secs seconds. + If the timeout expires, ovn-nbctl will exit with a + SIGALRM signal. (A timeout would normally happen only if + the database cannot be contacted, or if the system is overloaded.) +
+ +
--print-wait-time
+
+ When --wait is specified, the option + --print-wait-time can be used to print the time spent on + waiting, depending on the value specified in --wait + option. If --wait=sb is specified, it prints "ovn-northd + delay before processing", which is the time between the Northbound DB + update by the command and the moment when ovn-northd + starts processing the update, and "ovn-northd completion", which is the + time between the Northbound DB update and the moment when + ovn-northd completes the Southbound DB updating + successfully. If --wait=hv is specified, in addition to + the above information, it also prints "ovn-controller(s) completion", + which is the time between the Northbound DB update and the moment when + the slowest hypervisor finishes processing the update. +
+
+ +

Daemon Options

+ + +

Logging options

+ + +

Table Formatting Options

+ These options control the format of output from the list and + find commands. + + +

PKI Options

+

+ PKI configuration is required to use SSL for the connection to the + database. +

+ + + +

Other Options

+ + + +

Commands

+ +

+ The following sections describe the commands that ovn-nbctl + supports. +

+ +

General Commands

init
@@ -28,7 +346,7 @@
-

Logical Switch Commands

+

Logical Switch Commands

ls-add
@@ -74,7 +392,7 @@
-

ACL Commands

+

ACL Commands

These commands operates on ACL objects for a given entity. The entity can be either a logical switch or a port group. @@ -127,7 +445,7 @@ -

Logical Switch QoS Rule Commands

+

Logical Switch QoS Rule Commands

[--may-exist] qos-add switch direction priority match [dscp=dscp] [rate=rate [burst=burst]]
@@ -181,7 +499,7 @@
-

Meter Commands

+

Meter Commands

meter-add name action rate unit [burst]
@@ -234,7 +552,7 @@
-

Logical Switch Port Commands

+

Logical Switch Port Commands

[--may-exist] lsp-add switch port
@@ -490,7 +808,7 @@
-

Forwarding Group Commands

+

Forwarding Group Commands

[--liveness]fwd-group-add group switch vip vmac ports
@@ -528,7 +846,7 @@ be listed.
-

Logical Router Commands

+

Logical Router Commands

lr-add
@@ -574,7 +892,7 @@
-

Logical Router Port Commands

+

Logical Router Port Commands

[--may-exist] lrp-add router port mac network... [peer=peer]
@@ -654,7 +972,7 @@
-

Logical Router Static Route Commands

+

Logical Router Static Route Commands

[--may-exist] [--policy=POLICY] @@ -745,7 +1063,7 @@
-

Logical Router Policy Commands

+

Logical Router Policy Commands

[--may-exist]lr-policy-add @@ -817,7 +1135,7 @@
-

NAT Commands

+

NAT Commands

[--may-exist] [--stateless]lr-nat-add router type external_ip logical_ip [logical_port external_mac]
@@ -914,7 +1232,7 @@
-

Load Balancer Commands

+

Load Balancer Commands

[--may-exist | --add-duplicate | --reject | --event] lb-add lb vip ips [protocol]
@@ -1038,7 +1356,7 @@
-

DHCP Options commands

+

DHCP Options commands

dhcp-options-create cidr [key=value]
@@ -1068,7 +1386,7 @@
-

Port Group commands

+

Port Group commands

pg-add group [port]...
@@ -1090,7 +1408,7 @@
-

HA Chassis Group commands

+

HA Chassis Group commands

ha-chassis-group-add group
@@ -1131,38 +1449,7 @@
-

Database Commands

-

These commands query and modify the contents of ovsdb tables. - They are a slight abstraction of the ovsdb interface and - as such they operate at a lower level than other ovn-nbctl commands.

-

Identifying Tables, Records, and Columns

-

Each of these commands has a table parameter to identify a table - within the database. Many of them also take a record parameter - that identifies a particular record within a table. The record - parameter may be the UUID for a record, which may be abbreviated to its - first 4 (or more) hex digits, as long as that is unique. Many tables offer - additional ways to identify records. Some commands also take - column parameters that identify a particular field within the - records in a table.

- -

- For a list of tables and their columns, see ovn-nb(5) or - see the table listing from the --help option. -

- -

- Record names must be specified in full and with correct capitalization, - except that UUIDs may be abbreviated to their first 4 (or more) hex - digits, as long as that is unique within the table. Names of tables and - columns are not case-sensitive, and - and _ are - treated interchangeably. Unique abbreviations of table and column names - are acceptable, e.g. d or dhcp is sufficient - to identify the DHCP_Options table. -

- - - -

Synchronization Commands

+

Synchronization Commands

sync
@@ -1178,7 +1465,15 @@
-

Remote Connectivity Commands

+

Remote Connectivity Commands

+

+ These commands manipulate the connections column in the + NB_Global table and rows in the Connection + table. When ovsdb-server is configured to use the + connections column for OVSDB connections, this allows the + administrator to use ovn-nbctl to configure database + connections. +

get-connection
@@ -1198,7 +1493,7 @@
-

SSL Configuration Commands

+

SSL Configuration Commands

get-ssl
@@ -1218,258 +1513,77 @@
-

Daemon Mode

- -

- When it is invoked in the most ordinary way, ovn-nbctl - connects to an OVSDB server that hosts the northbound database, retrieves - a partial copy of the database that is complete enough to do its work, - sends a transaction request to the server, and receives and processes the - server's reply. In common interactive use, this is fine, but if the - database is large, the step in which ovn-nbctl retrieves a - partial copy of the database can take a long time, which yields poor - performance overall. -

- -

- To improve performance in such a case, ovn-nbctl offers a - "daemon mode," in which the user first starts ovn-nbctl - running in the background and afterward uses the daemon to execute - operations. Over several ovn-nbctl command invocations, - this performs better overall because it retrieves a copy of the database - only once at the beginning, not once per program run. -

- +

Database Commands

- Use the --detach option to start an ovn-nbctl - daemon. With this option, ovn-nbctl prints the name of a - control socket to stdout. The client should save this name in - environment variable OVN_NB_DAEMON. Under the Bourne shell - this might be done like this: + These commands query and modify the contents of ovsdb + tables. They are a slight abstraction of the ovsdb + interface and as such they operate at a lower level than other + ovn-nbctl commands.

-
-      export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
-    
- -

- When OVN_NB_DAEMON is set, ovn-nbctl - automatically and transparently uses the daemon to execute its commands. -

+

Identifying Tables, Records, and Columns

- When the daemon is no longer needed, kill it and unset the environment - variable, e.g.: + Each of these commands has a table parameter to identify a + table within the database. Many of them also take a record + parameter that identifies a particular record within a table. The + record parameter may be the UUID for a record, which may be + abbreviated to its first 4 (or more) hex digits, as long as that is + unique. Many tables offer additional ways to identify records. Some + commands also take column parameters that identify a + particular field within the records in a table.

-
-      kill $(cat $OVN_RUNDIR/ovn-nbctl.pid)
-      unset OVN_NB_DAEMON
-    
-

- When using daemon mode, an alternative to the OVN_NB_DAEMON environment - variable is to specify a path for the Unix socket. When starting the - ovn-nbctl daemon, specify the -u option with a full path to - the location of the socket file. Here is an exmple: + For a list of tables and their columns, see ovn-nb(5) or + see the table listing from the --help option.

-
-      ovn-nbctl --detach -u /tmp/mysock.ctl
-    
-

- Then to connect to the running daemon, use the -u option - with the full path to the socket created when the daemon was started: -

- -
-      ovn-nbctl -u /tmp/mysock.ctl show
-    
- -

- Daemon mode is experimental. + Record names must be specified in full and with correct capitalization, + except that UUIDs may be abbreviated to their first 4 (or more) hex + digits, as long as that is unique within the table. Names of tables and + columns are not case-sensitive, and - and _ are + treated interchangeably. Unique abbreviations of table and column names + are acceptable, e.g. d or dhcp is sufficient + to identify the DHCP_Options table.

-

Daemon Commands

+ -

- Daemon mode is internally implemented using the same mechanism used by - ovs-appctl. One may also use ovs-appctl - directly with the following commands: -

+

Environment

-
- run [options] command - [arg...] [-- [options] - command [arg...] ...] -
+
OVN_NB_DAEMON
- Instructs the daemon process to run one or more ovn-nbctl - commands described above and reply with the results of running these - commands. Accepts the --no-wait, --wait, - --timeout, --dry-run, --oneline, - and the options described under Table Formatting Options - in addition to the the command-specific options. + If set, this should name the Unix domain socket for an + ovn-nbctl server process. See Daemon Mode, + above, for more information.
-
exit
-
Causes ovn-nbctl to gracefully terminate.
-
- -

Options

- -
-
--no-wait | --wait=none
-
--wait=sb
-
--wait=hv
- +
OVN_NBCTL_OPTIONS
-

- These options control whether and how ovn-nbctl waits - for the OVN system to become up-to-date with changes made in an - ovn-nbctl invocation. -

- -

- By default, or if --no-wait or --wait=none, - ovn-nbctl exits immediately after confirming that - changes have been committed to the northbound database, without - waiting. -

- -

- With --wait=sb, before ovn-nbctl exits, it - waits for ovn-northd to bring the southbound database - up-to-date with the northbound database updates. -

- -

- With --wait=hv, before ovn-nbctl exits, it - additionally waits for all OVN chassis (hypervisors and gateways) to - become up-to-date with the northbound database updates. (This can - become an indefinite wait if any chassis is malfunctioning.) -

- -

- Ordinarily, --wait=sb or --wait=hv only - waits for changes by the current ovn-nbctl invocation to - take effect. This means that, if none of the commands supplied to - ovn-nbctl change the database, then the command does not - wait at all. Use the sync command to override this - behavior. -

+ If set, a set of options for ovn-nbctl to apply + automatically, in the same form as on the command line.
-
--print-wait-time
-
- When --wait is specified, the option - --print-wait-time can be used to print the time spent on - waiting, depending on the value specified in --wait option. - If --wait=sb is specified, it prints "ovn-northd delay - before processing", which is the time between the Northbound DB update by - the command and the moment when ovn-northd starts - processing the update, and "ovn-northd completion", which is the time - between the Northbound DB update and the moment when - ovn-northd completes the Southbound DB updating - successfully. If --wait=hv is specified, in addition to the - above information, it also prints "ovn-controller(s) completion", which - is the time between the Northbound DB update and the moment when the - slowest hypervisor finishes processing the update. -
- -
--db database
-
- The OVSDB database remote to contact. If the OVN_NB_DB - environment variable is set, its value is used as the default. - Otherwise, the default is unix:@RUNDIR@/ovnnb_db.sock, but this - default is unlikely to be useful outside of single-machine OVN test - environments. -
- -
--leader-only
-
--no-leader-only
-
- By default, or with --leader-only, when the database server - is a clustered database, ovn-nbctl will avoid servers other - than the cluster leader. This ensures that any data that - ovn-nbctl reads and reports is up-to-date. With - --no-leader-only, ovn-nbctl will use any server - in the cluster, which means that for read-only transactions it can report - and act on stale data (transactions that modify the database are always - serialized even with --no-leader-only). Refer to - Understanding Cluster Consistency in ovsdb(7) - for more information. -
- -
--shuffle-remotes
-
--no-shuffle-remotes
-
- By default, or with --shuffle-remotes, when there are - multiple remotes specified in the OVSDB connection string specified by - --db or the OVN_NB_DB environment variable, - the order of the remotes will be shuffled before the client tries to - connect. The remotes will be shuffled only once to a new order before - the first connection attempt. The following retries, if any, will - follow the same new order. The default behavior is to make sure - clients of a clustered database can distribute evenly to all memembers - of the cluster. With --no-shuffle-remotes, - ovn-nbctl will use the original order specified in the - connection string to connect. This allows user to specify the - preferred order, which is particularly useful for testing. -
- -
OVN_NBCTL_OPTIONS
-
-

- User can set one or more OVN_NBCTL_OPTIONS options in - environment variable. Under the Bourne shell this might be - done like this: -

- -
-          OVN_NBCTL_OPTIONS="--db=unix:nb1.ovsdb --no-leader-only"
-        
- -

- When OVN_NBCTL_OPTIONS is set, ovn-nbctl - automatically and transparently uses the environment variable to - execute its commands. However user can still over-ride environment - options by passing different in cli. -

- -

- When the environment variable is no longer needed, unset it, e.g.: -

- -
-          unset OVN_NBCTL_OPTIONS
-        
-
+
OVN_NB_DB
+
+ If set, the default database to contact when the --db + option is not used. +
-

Daemon Options

- - -

Logging options

- - -

Table Formatting Options

- These options control the format of output from the list and - find commands. - - -

PKI Options

-

- PKI configuration is required to use SSL for the connection to the - database. -

- - +

Exit Status

+
+
0
+
Successful program execution.
-

Other Options

+
1
+
Usage, syntax, or network error.
+
- +

See Also

+ ovn-nb(5). From patchwork Fri May 7 04:06:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475323 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxkV70vBz9sXS for ; Fri, 7 May 2021 14:08:02 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 36EFD83D9B; Fri, 7 May 2021 04:08:00 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RUGBpVQdJxqg; Fri, 7 May 2021 04:07:59 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTP id 902A583E6F; Fri, 7 May 2021 04:07:46 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 61EE6C000F; Fri, 7 May 2021 04:07:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 41C4AC000E for ; Fri, 7 May 2021 04:07:45 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 80E7740349 for ; Fri, 7 May 2021 04:07:29 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QSDGh8vUSKgR for ; Fri, 7 May 2021 04:07:14 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 4D360402F0 for ; Fri, 7 May 2021 04:07:14 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 8578BC0009; Fri, 7 May 2021 04:07:11 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:36 -0700 Message-Id: <20210507040659.26830-5-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 04/27] ovn-nbctl: Recommend ovn-appctl instead of ovs-appctl. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" They do exactly the same thing but ovn-appctl has more ovn in its name. Signed-off-by: Ben Pfaff Suggested-by: Mark Michelson --- utilities/ovn-nbctl.8.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 39f9381fdaae..73a0ee25fceb 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -114,7 +114,7 @@

Daemon mode is internally implemented using the same mechanism used by - ovs-appctl. One may also use ovs-appctl + ovn-appctl. One may also use ovn-appctl directly with the following commands:

@@ -1584,6 +1584,7 @@

See Also

- ovn-nb(5). + ovn-nb(5), + ovn-appctl(8). From patchwork Fri May 7 04:06:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475317 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxjt67dVz9sPf for ; Fri, 7 May 2021 14:07:30 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id CBD0560E33; Fri, 7 May 2021 04:07:28 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bZ5TmQfsbB_3; Fri, 7 May 2021 04:07:27 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTP id BE3A36090B; Fri, 7 May 2021 04:07:19 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 856CDC000D; Fri, 7 May 2021 04:07:19 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1E515C0022 for ; Fri, 7 May 2021 04:07:18 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 06077404AD for ; Fri, 7 May 2021 04:07:16 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RZ-NCA7qWIIu for ; Fri, 7 May 2021 04:07:16 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 1889E4049A for ; Fri, 7 May 2021 04:07:15 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 4DEE7C0004; Fri, 7 May 2021 04:07:13 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:37 -0700 Message-Id: <20210507040659.26830-6-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 05/27] ovn-nbctl: Daemon mode is no longer experimental. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Mark says that it was heavily used by ovn-kubernetes for years without any issues. Signed-off-by: Ben Pfaff Suggested-by: Mark Michelson --- NEWS | 1 + utilities/ovn-nbctl.8.xml | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/NEWS b/NEWS index c91bca0e2956..0565a0975d6e 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,7 @@ Post-v21.03.0 be used in the logical flow matches. CMS can consider setting this to false, if they want to use smart NICs which don't support offloading datapath flows with this field used. + - ovn-nbctl daemon mode is no longer considered experimental. OVN v21.03.0 - 12 Mar 2021 ------------------------- diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 73a0ee25fceb..afe3874e6d03 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -106,10 +106,6 @@ ovn-nbctl -u /tmp/mysock.ctl show -

- Daemon mode is experimental. -

-

Daemon Commands

From patchwork Fri May 7 04:06:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475325 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxkn1SjLz9sPf for ; Fri, 7 May 2021 14:08:17 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id C2C8784449; Fri, 7 May 2021 04:08:14 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MIKdI_F6XL6L; Fri, 7 May 2021 04:08:05 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id 347FB83D46; Fri, 7 May 2021 04:07:52 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 07E26C0011; Fri, 7 May 2021 04:07:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 14A80C001C for ; Fri, 7 May 2021 04:07:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 152C860A8E for ; Fri, 7 May 2021 04:07:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BEgsYpOzL6fr for ; Fri, 7 May 2021 04:07:19 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp3.osuosl.org (Postfix) with ESMTPS id E472860AA6 for ; Fri, 7 May 2021 04:07:17 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 0F9C9C0007; Fri, 7 May 2021 04:07:14 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:38 -0700 Message-Id: <20210507040659.26830-7-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 06/27] ovn-nbctl: Refactor into infrastructure and northbound details. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" In an upcoming commit, this will allow adding daemon mode to ovn-sbctl without having a lot of duplicated code. Signed-off-by: Ben Pfaff --- utilities/automake.mk | 5 +- utilities/ovn-dbctl.c | 1214 ++++++++++++++++++++++++++++++++++++ utilities/ovn-dbctl.h | 60 ++ utilities/ovn-nbctl.c | 1366 ++++------------------------------------- 4 files changed, 1411 insertions(+), 1234 deletions(-) create mode 100644 utilities/ovn-dbctl.c create mode 100644 utilities/ovn-dbctl.h diff --git a/utilities/automake.mk b/utilities/automake.mk index c4a6d248c274..50c0cfded018 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -71,7 +71,10 @@ utilities/ovn-lib: $(top_builddir)/config.status # ovn-nbctl bin_PROGRAMS += utilities/ovn-nbctl -utilities_ovn_nbctl_SOURCES = utilities/ovn-nbctl.c +utilities_ovn_nbctl_SOURCES = \ + utilities/ovn-dbctl.c \ + utilities/ovn-dbctl.h \ + utilities/ovn-nbctl.c utilities_ovn_nbctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la # ovn-sbctl diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c new file mode 100644 index 000000000000..28ebc6267066 --- /dev/null +++ b/utilities/ovn-dbctl.c @@ -0,0 +1,1214 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ovn-dbctl.h" + +#include + +#include "command-line.h" +#include "daemon.h" +#include "db-ctl-base.h" +#include "fatal-signal.h" +#include "jsonrpc.h" +#include "memory.h" +#include "openvswitch/poll-loop.h" +#include "openvswitch/vlog.h" +#include "ovn-util.h" +#include "ovsdb-idl.h" +#include "process.h" +#include "simap.h" +#include "stream-ssl.h" +#include "svec.h" +#include "table.h" +#include "timer.h" +#include "unixctl.h" +#include "util.h" + +VLOG_DEFINE_THIS_MODULE(ovn_dbctl); + +/* --db: The database server to contact. */ +static const char *db; + +/* --oneline: Write each command's output as a single line? */ +static bool oneline; + +/* --dry-run: Do not commit any changes. */ +static bool dry_run; + +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +static bool print_wait_time = false; + +/* --timeout: Time to wait for a connection to 'db'. */ +static unsigned int timeout; + +/* Format for table output. */ +static struct table_style table_style = TABLE_STYLE_DEFAULT; + +/* The IDL we're using and the current transaction, if any. This is for use by + * ovn_dbctl_exit() only, to allow it to clean up. Other code should use its + * context arguments. */ +static struct ovsdb_idl *the_idl; +static struct ovsdb_idl_txn *the_idl_txn; + +/* --leader-only, --no-leader-only: Only accept the leader in a cluster. */ +static int leader_only = true; + +/* --shuffle-remotes, --no-shuffle-remotes: Shuffle the order of remotes that + * are specified in the connetion method string. */ +static int shuffle_remotes = true; + +/* --unixctl-path: Path to use for unixctl server socket, for daemon mode. */ +static char *unixctl_path; + +static unixctl_cb_func server_cmd_exit; +static unixctl_cb_func server_cmd_run; + +static struct option *get_all_options(void); +static bool has_option(const struct ovs_cmdl_parsed_option *, size_t n, + int option); +static void dbctl_client(const struct ovn_dbctl_options *dbctl_options, + const char *socket_name, + const struct ovs_cmdl_parsed_option *, size_t n, + int argc, char *argv[]); +static bool will_detach(const struct ovs_cmdl_parsed_option *, size_t n); +static void apply_options_direct(const struct ovn_dbctl_options *dbctl_options, + const struct ovs_cmdl_parsed_option *, + size_t n, struct shash *local_options); +static char * OVS_WARN_UNUSED_RESULT run_prerequisites( + const struct ovn_dbctl_options *dbctl_options, + struct ctl_command[], size_t n_commands, struct ovsdb_idl *); +static char * OVS_WARN_UNUSED_RESULT do_dbctl( + const struct ovn_dbctl_options *dbctl_options, + const char *args, struct ctl_command *, size_t n, + struct ovsdb_idl *, const struct timer *, bool *retry); +static char * OVS_WARN_UNUSED_RESULT main_loop( + const struct ovn_dbctl_options *, const char *args, + struct ctl_command *commands, size_t n_commands, + struct ovsdb_idl *idl, const struct timer *); +static void server_loop(const struct ovn_dbctl_options *dbctl_options, + struct ovsdb_idl *idl, int argc, char *argv[]); +static void ovn_dbctl_exit(int status); + +int +ovn_dbctl_main(int argc, char *argv[], + const struct ovn_dbctl_options *dbctl_options) +{ + struct ovsdb_idl *idl; + struct shash local_options; + + ovn_set_program_name(argv[0]); + fatal_ignore_sigpipe(); + vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN); + vlog_set_levels_from_string_assert("reconnect:warn"); + + ctl_init__(dbctl_options->idl_class, + dbctl_options->tables, + dbctl_options->cmd_show_table, + ovn_dbctl_exit); + ctl_register_commands(dbctl_options->commands); + + /* Check if options are set via env var. */ + char **argv_ = ovs_cmdl_env_parse_all( + &argc, argv, getenv(dbctl_options->options_env_var_name)); + + /* This utility has three operation modes: + * + * - Direct: Executes commands by contacting ovsdb-server directly. + * + * - Server: Runs in the background as a daemon waiting for requests + * from a process running in client mode. + * + * - Client: Executes commands by passing them to a process running in + * the server mode. + * + * At this point we don't know what mode we're running in. The mode partly + * depends on the command line. So, for now we transform the command line + * into a parsed form, and figure out what to do with it later. + */ + struct ovs_cmdl_parsed_option *parsed_options; + size_t n_parsed_options; + char *error_s = ovs_cmdl_parse_all(argc, argv_, get_all_options(), + &parsed_options, &n_parsed_options); + if (error_s) { + ctl_fatal("%s", error_s); + } + + /* Now figure out the operation mode: + * + * - A --detach option implies server mode. + * + * - An OVN_??_DAEMON environment variable implies client mode. + * + * - Otherwise, we're in direct mode. */ + const char *socket_name = (unixctl_path ? unixctl_path + : getenv(dbctl_options->daemon_env_var_name)); + if (((socket_name && socket_name[0]) + || has_option(parsed_options, n_parsed_options, 'u')) + && !will_detach(parsed_options, n_parsed_options)) { + dbctl_client(dbctl_options, socket_name, + parsed_options, n_parsed_options, argc, argv_); + } + + /* Parse command line. */ + shash_init(&local_options); + apply_options_direct(dbctl_options, + parsed_options, n_parsed_options, &local_options); + free(parsed_options); + + bool daemon_mode = false; + if (get_detach()) { + if (argc != optind) { + ctl_fatal("non-option arguments not supported with --detach " + "(use --help for help)"); + } + daemon_mode = true; + } + /* Initialize IDL. */ + idl = the_idl = ovsdb_idl_create_unconnected(dbctl_options->idl_class, + true); + ovsdb_idl_set_shuffle_remotes(idl, shuffle_remotes); + /* "retry" is true iff in daemon mode. */ + ovsdb_idl_set_remote(idl, db, daemon_mode); + ovsdb_idl_set_leader_only(idl, leader_only); + + if (daemon_mode) { + server_loop(dbctl_options, idl, argc, argv_); + } else { + struct ctl_command *commands; + size_t n_commands; + char *error; + + error = ctl_parse_commands(argc - optind, argv_ + optind, + &local_options, &commands, &n_commands); + if (error) { + ctl_fatal("%s", error); + } + + char *args = process_escape_args(argv_); + VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG, + "Called as %s", args); + + ctl_timeout_setup(timeout); + + error = run_prerequisites(dbctl_options, commands, n_commands, idl); + if (error) { + goto cleanup; + } + + error = main_loop(dbctl_options, args, commands, n_commands, idl, NULL); + +cleanup: + free(args); + + struct ctl_command *c; + for (c = commands; c < &commands[n_commands]; c++) { + ds_destroy(&c->output); + table_destroy(c->table); + free(c->table); + shash_destroy_free_data(&c->options); + } + free(commands); + if (error) { + ctl_fatal("%s", error); + } + } + + ovsdb_idl_destroy(idl); + idl = the_idl = NULL; + + for (int i = 0; i < argc; i++) { + free(argv_[i]); + } + free(argv_); + exit(EXIT_SUCCESS); +} + +static char * +main_loop(const struct ovn_dbctl_options *dbctl_options, + const char *args, struct ctl_command *commands, size_t n_commands, + struct ovsdb_idl *idl, const struct timer *wait_timeout) +{ + unsigned int seqno; + bool idl_ready; + + /* Execute the commands. + * + * 'seqno' is the database sequence number for which we last tried to + * execute our transaction. There's no point in trying to commit more than + * once for any given sequence number, because if the transaction fails + * it's because the database changed and we need to obtain an up-to-date + * view of the database before we try the transaction again. */ + seqno = ovsdb_idl_get_seqno(idl); + + /* IDL might have already obtained the database copy during previous + * invocation. If so, we can't expect the sequence number to change before + * we issue any new requests. */ + idl_ready = ovsdb_idl_has_ever_connected(idl); + for (;;) { + ovsdb_idl_run(idl); + if (!ovsdb_idl_is_alive(idl)) { + int retval = ovsdb_idl_get_last_error(idl); + ctl_fatal("%s: database connection failed (%s)", + db, ovs_retval_to_string(retval)); + } + + if (idl_ready || seqno != ovsdb_idl_get_seqno(idl)) { + idl_ready = false; + seqno = ovsdb_idl_get_seqno(idl); + + bool retry; + char *error = do_dbctl(dbctl_options, + args, commands, n_commands, idl, + wait_timeout, &retry); + if (error) { + return error; + } + if (!retry) { + return NULL; + } + } + + if (seqno == ovsdb_idl_get_seqno(idl)) { + ovsdb_idl_wait(idl); + poll_block(); + } + } + + return NULL; +} + +/* All options that affect the main loop and are not external. */ +#define MAIN_LOOP_OPTION_ENUMS \ + OPT_NO_WAIT, \ + OPT_WAIT, \ + OPT_PRINT_WAIT_TIME, \ + OPT_DRY_RUN, \ + OPT_ONELINE + +#define MAIN_LOOP_LONG_OPTIONS \ + {"no-wait", no_argument, NULL, OPT_NO_WAIT}, \ + {"wait", required_argument, NULL, OPT_WAIT}, \ + {"print-wait-time", no_argument, NULL, OPT_PRINT_WAIT_TIME}, \ + {"dry-run", no_argument, NULL, OPT_DRY_RUN}, \ + {"oneline", no_argument, NULL, OPT_ONELINE}, \ + {"timeout", required_argument, NULL, 't'} + +enum { + OPT_DB = UCHAR_MAX + 1, + OPT_NO_SYSLOG, + OPT_LOCAL, + OPT_COMMANDS, + OPT_OPTIONS, + OPT_LEADER_ONLY, + OPT_NO_LEADER_ONLY, + OPT_SHUFFLE_REMOTES, + OPT_NO_SHUFFLE_REMOTES, + OPT_BOOTSTRAP_CA_CERT, + MAIN_LOOP_OPTION_ENUMS, + OVN_DAEMON_OPTION_ENUMS, + VLOG_OPTION_ENUMS, + TABLE_OPTION_ENUMS, + SSL_OPTION_ENUMS, +}; + +static char * OVS_WARN_UNUSED_RESULT +handle_main_loop_option(int opt, const char *arg, bool *handled) +{ + ovs_assert(handled); + *handled = true; + + switch (opt) { + case OPT_ONELINE: + oneline = true; + break; + + case OPT_NO_WAIT: + wait_type = NBCTL_WAIT_NONE; + break; + + case OPT_WAIT: + if (!strcmp(arg, "none")) { + wait_type = NBCTL_WAIT_NONE; + } else if (!strcmp(arg, "sb")) { + wait_type = NBCTL_WAIT_SB; + } else if (!strcmp(arg, "hv")) { + wait_type = NBCTL_WAIT_HV; + } else { + return xstrdup("argument to --wait must be " + "\"none\", \"sb\", or \"hv\""); + } + break; + + case OPT_PRINT_WAIT_TIME: + print_wait_time = true; + break; + + case OPT_DRY_RUN: + dry_run = true; + break; + + case 't': + if (!str_to_uint(arg, 10, &timeout) || !timeout) { + return xasprintf("value %s on -t or --timeout is invalid", arg); + } + break; + + default: + *handled = false; + break; + } + + return NULL; +} + +static char * OVS_WARN_UNUSED_RESULT +build_short_options(const struct option *long_options, bool print_errors) +{ + char *tmp, *short_options; + + tmp = ovs_cmdl_long_options_to_short_options(long_options); + short_options = xasprintf("+%s%s", print_errors ? "" : ":", tmp); + free(tmp); + + return short_options; +} + +static struct option * OVS_WARN_UNUSED_RESULT +append_command_options(const struct option *options, int opt_val) +{ + struct option *o; + size_t n_allocated; + size_t n_existing; + int i; + + for (i = 0; options[i].name; i++) { + ; + } + n_allocated = i + 1; + n_existing = i; + + /* We want to parse both global and command-specific options here, but + * getopt_long() isn't too convenient for the job. We copy our global + * options into a dynamic array, then append all of the command-specific + * options. */ + o = xmemdup(options, n_allocated * sizeof *options); + ctl_add_cmd_options(&o, &n_existing, &n_allocated, opt_val); + + return o; +} + +static struct option * +get_all_options(void) +{ + static const struct option global_long_options[] = { + {"db", required_argument, NULL, OPT_DB}, + {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, + {"help", no_argument, NULL, 'h'}, + {"commands", no_argument, NULL, OPT_COMMANDS}, + {"options", no_argument, NULL, OPT_OPTIONS}, + {"leader-only", no_argument, NULL, OPT_LEADER_ONLY}, + {"no-leader-only", no_argument, NULL, OPT_NO_LEADER_ONLY}, + {"shuffle-remotes", no_argument, NULL, OPT_SHUFFLE_REMOTES}, + {"no-shuffle-remotes", no_argument, NULL, OPT_NO_SHUFFLE_REMOTES}, + {"version", no_argument, NULL, 'V'}, + {"unixctl", required_argument, NULL, 'u'}, + MAIN_LOOP_LONG_OPTIONS, + OVN_DAEMON_LONG_OPTIONS, + VLOG_LONG_OPTIONS, + STREAM_SSL_LONG_OPTIONS, + {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, + TABLE_LONG_OPTIONS, + {NULL, 0, NULL, 0}, + }; + + static struct option *options; + if (!options) { + options = append_command_options(global_long_options, OPT_LOCAL); + } + + return options; +} + +static bool +has_option(const struct ovs_cmdl_parsed_option *parsed_options, size_t n, + int option) +{ + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n]; po++) { + if (po->o->val == option) { + return true; + } + } + return false; +} + +static bool +will_detach(const struct ovs_cmdl_parsed_option *parsed_options, size_t n) +{ + return has_option(parsed_options, n, OVN_OPT_DETACH); +} + +static char * OVS_WARN_UNUSED_RESULT +add_local_option(const char *name, const char *arg, + struct shash *local_options) +{ + char *full_name = xasprintf("--%s", name); + if (shash_find(local_options, full_name)) { + char *error = xasprintf("'%s' option specified multiple times", + full_name); + free(full_name); + return error; + } + shash_add_nocopy(local_options, full_name, nullable_xstrdup(arg)); + return NULL; +} + +static void +apply_options_direct(const struct ovn_dbctl_options *dbctl_options, + const struct ovs_cmdl_parsed_option *parsed_options, + size_t n, struct shash *local_options) +{ + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n]; po++) { + bool handled; + char *error = handle_main_loop_option(po->o->val, po->arg, &handled); + if (error) { + ctl_fatal("%s", error); + } + if (handled) { + continue; + } + + optarg = po->arg; + switch (po->o->val) { + case OPT_DB: + db = po->arg; + break; + + case OPT_NO_SYSLOG: + vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); + break; + + case OPT_LOCAL: + error = add_local_option(po->o->name, po->arg, local_options); + if (error) { + ctl_fatal("%s", error); + } + break; + + case 'h': + dbctl_options->usage(); + exit(EXIT_SUCCESS); + + case OPT_COMMANDS: + ctl_print_commands(); + /* fall through */ + + case OPT_OPTIONS: + ctl_print_options(get_all_options()); + /* fall through */ + + case OPT_LEADER_ONLY: + leader_only = true; + break; + + case OPT_NO_LEADER_ONLY: + leader_only = false; + break; + + case OPT_SHUFFLE_REMOTES: + shuffle_remotes = true; + break; + + case OPT_NO_SHUFFLE_REMOTES: + shuffle_remotes = false; + break; + + case 'u': + unixctl_path = optarg; + break; + + case 'V': + ovn_print_version(0, 0); + printf("DB Schema %s\n", dbctl_options->db_version); + exit(EXIT_SUCCESS); + + OVN_DAEMON_OPTION_HANDLERS + VLOG_OPTION_HANDLERS + TABLE_OPTION_HANDLERS(&table_style) + STREAM_SSL_OPTION_HANDLERS + + case OPT_BOOTSTRAP_CA_CERT: + stream_ssl_set_ca_cert_file(po->arg, true); + break; + + case '?': + exit(EXIT_FAILURE); + + default: + OVS_NOT_REACHED(); + + case 0: + break; + } + } + + if (!db) { + db = dbctl_options->default_db; + } +} + +static char * +run_prerequisites(const struct ovn_dbctl_options *dbctl_options, + struct ctl_command *commands, size_t n_commands, + struct ovsdb_idl *idl) +{ + dbctl_options->add_base_prerequisites(idl, wait_type); + + for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) { + if (c->syntax->prerequisites) { + struct ctl_context ctx; + + ds_init(&c->output); + c->table = NULL; + + ctl_context_init(&ctx, c, idl, NULL, NULL, NULL); + (c->syntax->prerequisites)(&ctx); + if (ctx.error) { + char *error = xstrdup(ctx.error); + ctl_context_done(&ctx, c); + return error; + } + ctl_context_done(&ctx, c); + + ovs_assert(!c->output.string); + ovs_assert(!c->table); + } + } + + return NULL; +} + +static void +oneline_format(struct ds *lines, struct ds *s) +{ + size_t j; + + ds_chomp(lines, '\n'); + for (j = 0; j < lines->length; j++) { + int ch = lines->string[j]; + switch (ch) { + case '\n': + ds_put_cstr(s, "\\n"); + break; + + case '\\': + ds_put_cstr(s, "\\\\"); + break; + + default: + ds_put_char(s, ch); + } + } + ds_put_char(s, '\n'); +} + +static void +oneline_print(struct ds *lines) +{ + struct ds s = DS_EMPTY_INITIALIZER; + oneline_format(lines, &s); + fputs(ds_cstr(&s), stdout); + ds_destroy(&s); +} + +static char * +do_dbctl(const struct ovn_dbctl_options *dbctl_options, + const char *args, struct ctl_command *commands, size_t n_commands, + struct ovsdb_idl *idl, const struct timer *wait_timeout, bool *retry) +{ + struct ovsdb_idl_txn *txn; + enum ovsdb_idl_txn_status status; + struct ovsdb_symbol_table *symtab; + struct ctl_command *c; + struct shash_node *node; + char *error = NULL; + + ovs_assert(retry); + + txn = the_idl_txn = ovsdb_idl_txn_create(idl); + if (dry_run) { + ovsdb_idl_txn_set_dry_run(txn); + } + + ovsdb_idl_txn_add_comment(txn, "%s: %s", program_name, args); + + dbctl_options->pre_execute(idl, txn, wait_type); + + symtab = ovsdb_symbol_table_create(); + for (c = commands; c < &commands[n_commands]; c++) { + ds_init(&c->output); + c->table = NULL; + } + struct ctl_context *ctx = dbctl_options->ctx_create(); + ctl_context_init(ctx, NULL, idl, txn, symtab, NULL); + for (c = commands; c < &commands[n_commands]; c++) { + ctl_context_init_command(ctx, c); + if (c->syntax->run) { + (c->syntax->run)(ctx); + } + if (ctx->error) { + error = xstrdup(ctx->error); + ctl_context_done(ctx, c); + goto out_error; + } + ctl_context_done_command(ctx, c); + + if (ctx->try_again) { + ctl_context_done(ctx, NULL); + goto try_again; + } + } + ctl_context_done(ctx, NULL); + + SHASH_FOR_EACH (node, &symtab->sh) { + struct ovsdb_symbol *symbol = node->data; + if (!symbol->created) { + error = xasprintf("row id \"%s\" is referenced but never created " + "(e.g. with \"-- --id=%s create ...\")", + node->name, node->name); + goto out_error; + } + if (!symbol->strong_ref) { + if (!symbol->weak_ref) { + VLOG_WARN("row id \"%s\" was created but no reference to it " + "was inserted, so it will not actually appear in " + "the database", node->name); + } else { + VLOG_WARN("row id \"%s\" was created but only a weak " + "reference to it was inserted, so it will not " + "actually appear in the database", node->name); + } + } + } + + long long int start_time = time_wall_msec(); + status = ovsdb_idl_txn_commit_block(txn); + if (status == TXN_UNCHANGED || status == TXN_SUCCESS) { + for (c = commands; c < &commands[n_commands]; c++) { + if (c->syntax->postprocess) { + ctl_context_init(ctx, c, idl, txn, symtab, NULL); + (c->syntax->postprocess)(ctx); + if (ctx->error) { + error = xstrdup(ctx->error); + ctl_context_done(ctx, c); + goto out_error; + } + ctl_context_done(ctx, c); + } + } + } + + switch (status) { + case TXN_UNCOMMITTED: + case TXN_INCOMPLETE: + OVS_NOT_REACHED(); + + case TXN_ABORTED: + /* Should not happen--we never call ovsdb_idl_txn_abort(). */ + error = xstrdup("transaction aborted"); + goto out_error; + + case TXN_UNCHANGED: + case TXN_SUCCESS: + break; + + case TXN_TRY_AGAIN: + goto try_again; + + case TXN_ERROR: + error = xasprintf("transaction error: %s", + ovsdb_idl_txn_get_error(txn)); + goto out_error; + + case TXN_NOT_LOCKED: + /* Should not happen--we never call ovsdb_idl_set_lock(). */ + error = xstrdup("database not locked"); + goto out_error; + + default: + OVS_NOT_REACHED(); + } + + for (c = commands; c < &commands[n_commands]; c++) { + struct ds *ds = &c->output; + + if (c->table) { + table_print(c->table, &table_style); + } else if (oneline) { + oneline_print(ds); + } else { + fputs(ds_cstr(ds), stdout); + } + } + + if (dbctl_options->post_execute) { + error = dbctl_options->post_execute(idl, txn, status, wait_type, + wait_timeout, start_time, + print_wait_time); + if (error) { + goto out_error; + } + } + + dbctl_options->ctx_destroy(ctx); + ovsdb_symbol_table_destroy(symtab); + ovsdb_idl_txn_destroy(txn); + the_idl_txn = NULL; + + *retry = false; + return NULL; + +try_again: + /* Our transaction needs to be rerun, or a prerequisite was not met. Free + * resources and return so that the caller can try again. */ + *retry = true; + +out_error: + ovsdb_idl_txn_abort(txn); + ovsdb_idl_txn_destroy(txn); + the_idl_txn = NULL; + + dbctl_options->ctx_destroy(ctx); + ovsdb_symbol_table_destroy(symtab); + return error; +} + +/* Frees the current transaction and the underlying IDL and then calls + * exit(status). + * + * Freeing the transaction and the IDL is not strictly necessary, but it makes + * for a clean memory leak report from valgrind in the normal case. That makes + * it easier to notice real memory leaks. */ +static void +ovn_dbctl_exit(int status) +{ + if (the_idl_txn) { + ovsdb_idl_txn_abort(the_idl_txn); + ovsdb_idl_txn_destroy(the_idl_txn); + } + ovsdb_idl_destroy(the_idl); + exit(status); +} + +/* Server implementation. */ + +#undef ctl_fatal + +static const struct option * +find_option_by_value(const struct option *options, int value) +{ + const struct option *o; + + for (o = options; o->name; o++) { + if (o->val == value) { + return o; + } + } + return NULL; +} + +static char * OVS_WARN_UNUSED_RESULT +server_parse_options(int argc, char *argv[], struct shash *local_options, + int *n_options_p) +{ + static const struct option global_long_options[] = { + VLOG_LONG_OPTIONS, + MAIN_LOOP_LONG_OPTIONS, + TABLE_LONG_OPTIONS, + {NULL, 0, NULL, 0}, + }; + const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1; + char *short_options; + struct option *options; + char *error = NULL; + + ovs_assert(n_options_p); + + short_options = build_short_options(global_long_options, false); + options = append_command_options(global_long_options, OPT_LOCAL); + + optind = 0; + opterr = 0; + for (;;) { + int idx; + int c; + + c = getopt_long(argc, argv, short_options, options, &idx); + if (c == -1) { + break; + } + + bool handled; + error = handle_main_loop_option(c, optarg, &handled); + if (error) { + goto out; + } + if (handled) { + continue; + } + + switch (c) { + case OPT_LOCAL: + error = add_local_option(options[idx].name, optarg, local_options); + if (error) { + goto out; + } + break; + + VLOG_OPTION_HANDLERS + TABLE_OPTION_HANDLERS(&table_style) + + case '?': + if (find_option_by_value(options, optopt)) { + error = xasprintf("option '%s' doesn't allow an argument", + argv[optind - 1]); + } else if (optopt) { + error = xasprintf("unrecognized option '%c'", optopt); + } else { + error = xasprintf("unrecognized option '%s'", argv[optind - 1]); + } + goto out; + break; + + case ':': + error = xasprintf("option '%s' requires an argument", + argv[optind - 1]); + goto out; + break; + + case 0: + break; + + default: + error = xasprintf("unhandled option '%c'", c); + goto out; + break; + } + } + *n_options_p = optind; + +out: + for (int i = n_global_long_options; options[i].name; i++) { + free(CONST_CAST(char *, options[i].name)); + } + free(options); + free(short_options); + + return error; +} + +static void +server_cmd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *exiting_) +{ + bool *exiting = exiting_; + *exiting = true; + unixctl_command_reply(conn, NULL); +} + +struct server_cmd_run_ctx { + struct ovsdb_idl *idl; + const struct ovn_dbctl_options *dbctl_options; +}; + +static void +server_cmd_run(struct unixctl_conn *conn, int argc, const char **argv_, + void *ctx_) +{ + struct server_cmd_run_ctx *ctx = ctx_; + struct ovsdb_idl *idl = ctx->idl; + const struct ovn_dbctl_options *dbctl_options = ctx->dbctl_options; + + struct ctl_command *commands = NULL; + struct shash local_options; + size_t n_commands = 0; + int n_options = 0; + char *error = NULL; + + /* Copy args so that getopt() can permute them. Leave last entry NULL. */ + char **argv = xcalloc(argc + 1, sizeof *argv); + for (int i = 0; i < argc; i++) { + argv[i] = xstrdup(argv_[i]); + } + + /* Reset global state. */ + oneline = false; + dry_run = false; + wait_type = NBCTL_WAIT_NONE; + timeout = 0; + table_style = table_style_default; + + /* Parse commands & options. */ + char *args = process_escape_args(argv); + shash_init(&local_options); + error = server_parse_options(argc, argv, &local_options, &n_options); + if (error) { + unixctl_command_reply_error(conn, error); + goto out; + } + error = ctl_parse_commands(argc - n_options, argv + n_options, + &local_options, &commands, &n_commands); + if (error) { + unixctl_command_reply_error(conn, error); + goto out; + } + VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG, + "Running command %s", args); + + struct timer *wait_timeout = NULL; + struct timer wait_timeout_; + if (timeout) { + wait_timeout = &wait_timeout_; + timer_set_duration(wait_timeout, timeout * 1000); + } + + error = run_prerequisites(dbctl_options, commands, n_commands, idl); + if (error) { + unixctl_command_reply_error(conn, error); + goto out; + } + error = main_loop(dbctl_options, args, commands, n_commands, idl, wait_timeout); + if (error) { + unixctl_command_reply_error(conn, error); + goto out; + } + + struct ds output = DS_EMPTY_INITIALIZER; + table_format_reset(); + for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) { + if (c->table) { + table_format(c->table, &table_style, &output); + } else if (oneline) { + oneline_format(&c->output, &output); + } else { + ds_put_cstr(&output, ds_cstr_ro(&c->output)); + } + } + unixctl_command_reply(conn, ds_cstr_ro(&output)); + ds_destroy(&output); + +out: + free(error); + + struct ctl_command *c; + for (c = commands; c < &commands[n_commands]; c++) { + ds_destroy(&c->output); + table_destroy(c->table); + free(c->table); + shash_destroy_free_data(&c->options); + } + free(commands); + shash_destroy_free_data(&local_options); + free(args); + for (int i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); +} + +static void +server_loop(const struct ovn_dbctl_options *dbctl_options, + struct ovsdb_idl *idl, int argc, char *argv[]) +{ + struct unixctl_server *server = NULL; + bool exiting = false; + + service_start(&argc, &argv); + daemonize_start(false); + + char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path); + int error = unixctl_server_create(abs_unixctl_path, &server); + free(abs_unixctl_path); + + if (error) { + ctl_fatal("failed to create unixctl server (%s)", + ovs_retval_to_string(error)); + } + puts(unixctl_server_get_path(server)); + fflush(stdout); + + struct server_cmd_run_ctx server_cmd_run_ctx = { + .idl = idl, + .dbctl_options = dbctl_options + }; + unixctl_command_register("run", "", 0, INT_MAX, server_cmd_run, + &server_cmd_run_ctx); + unixctl_command_register("exit", "", 0, 0, server_cmd_exit, &exiting); + + for (;;) { + memory_run(); + if (memory_should_report()) { + struct simap usage = SIMAP_INITIALIZER(&usage); + + /* Nothing special to report yet. */ + memory_report(&usage); + simap_destroy(&usage); + } + + ovsdb_idl_run(idl); + if (!ovsdb_idl_is_alive(idl)) { + int retval = ovsdb_idl_get_last_error(idl); + ctl_fatal("%s: database connection failed (%s)", + db, ovs_retval_to_string(retval)); + } + + if (ovsdb_idl_has_ever_connected(idl)) { + daemonize_complete(); + } + unixctl_server_run(server); + + if (exiting) { + break; + } + + memory_wait(); + ovsdb_idl_wait(idl); + unixctl_server_wait(server); + poll_block(); + } + + unixctl_server_destroy(server); +} + +static void +dbctl_client(const struct ovn_dbctl_options *dbctl_options, + const char *socket_name, + const struct ovs_cmdl_parsed_option *parsed_options, size_t n, + int argc, char *argv[]) +{ + struct svec args = SVEC_EMPTY_INITIALIZER; + + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n]; po++) { + optarg = po->arg; + switch (po->o->val) { + case OPT_DB: + VLOG_WARN("not using %s daemon because of %s option", + program_name, po->o->name); + svec_destroy(&args); + return; + + case OPT_NO_SYSLOG: + vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); + break; + + case 'h': + dbctl_options->usage(); + exit(EXIT_SUCCESS); + + case OPT_COMMANDS: + ctl_print_commands(); + /* fall through */ + + case OPT_OPTIONS: + ctl_print_options(get_all_options()); + /* fall through */ + + case OPT_LEADER_ONLY: + case OPT_NO_LEADER_ONLY: + case OPT_SHUFFLE_REMOTES: + case OPT_NO_SHUFFLE_REMOTES: + case OPT_BOOTSTRAP_CA_CERT: + STREAM_SSL_CASES + OVN_DAEMON_OPTION_CASES + VLOG_INFO("using %s daemon, ignoring %s option", + program_name, po->o->name); + break; + + case 'u': + socket_name = optarg; + break; + + case 'V': + ovs_print_version(0, 0); + printf("DB Schema %s\n", dbctl_options->db_version); + exit(EXIT_SUCCESS); + + case 't': + if (!str_to_uint(po->arg, 10, &timeout) || !timeout) { + ctl_fatal("value %s on -t or --timeout is invalid", po->arg); + } + break; + + VLOG_OPTION_HANDLERS + + case OPT_LOCAL: + default: + if (po->arg) { + svec_add_nocopy(&args, + xasprintf("--%s=%s", po->o->name, po->arg)); + } else { + svec_add_nocopy(&args, xasprintf("--%s", po->o->name)); + } + break; + } + } + + ovs_assert(socket_name && socket_name[0]); + + svec_add(&args, "--"); + for (int i = optind; i < argc; i++) { + svec_add(&args, argv[i]); + } + + ctl_timeout_setup(timeout); + + struct jsonrpc *client; + int error = unixctl_client_create(socket_name, &client); + if (error) { + ctl_fatal("%s: could not connect to %s daemon (%s); " + "unset %s to avoid using daemon", + socket_name, program_name, ovs_strerror(error), + dbctl_options->daemon_env_var_name); + } + + char *cmd_result; + char *cmd_error; + error = unixctl_client_transact(client, "run", + args.n, args.names, + &cmd_result, &cmd_error); + if (error) { + ctl_fatal("%s: transaction error (%s)", + socket_name, ovs_strerror(error)); + } + svec_destroy(&args); + + int exit_status; + if (cmd_error) { + exit_status = EXIT_FAILURE; + fprintf(stderr, "%s: %s", program_name, cmd_error); + } else { + exit_status = EXIT_SUCCESS; + fputs(cmd_result, stdout); + } + free(cmd_result); + free(cmd_error); + jsonrpc_close(client); + exit(exit_status); +} diff --git a/utilities/ovn-dbctl.h b/utilities/ovn-dbctl.h new file mode 100644 index 000000000000..5accf3c5e028 --- /dev/null +++ b/utilities/ovn-dbctl.h @@ -0,0 +1,60 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVN_DBCTL_H +#define OVN_DBCTL_H 1 + +/* ovn-nbctl infrastructure code. */ + +#include +#include "ovsdb-idl.h" + +struct timer; + +enum nbctl_wait_type { + NBCTL_WAIT_NONE, /* Do not wait. */ + NBCTL_WAIT_SB, /* Wait for southbound database updates. */ + NBCTL_WAIT_HV /* Wait for hypervisors to catch up. */ +}; + +struct ovn_dbctl_options { + const char *db_version; /* Database schema version. */ + const char *default_db; /* Default database remote. */ + + /* Names of important environment variables. */ + const char *options_env_var_name; /* OVN_??_OPTIONS. */ + const char *daemon_env_var_name; /* OVN_??_DAEMON. */ + + const struct ovsdb_idl_class *idl_class; + const struct ctl_table_class *tables; + struct cmd_show_table *cmd_show_table; + const struct ctl_command_syntax *commands; + + void (*usage)(void); + + void (*add_base_prerequisites)(struct ovsdb_idl *, enum nbctl_wait_type); + void (*pre_execute)(struct ovsdb_idl *, struct ovsdb_idl_txn *, + enum nbctl_wait_type); + char *(*post_execute)(struct ovsdb_idl *, struct ovsdb_idl_txn *, + enum ovsdb_idl_txn_status, enum nbctl_wait_type, + const struct timer *wait_timeout, + long long int start_time, bool print_wait_time); + + struct ctl_context *(*ctx_create)(void); + void (*ctx_destroy)(struct ctl_context *); +}; + +int ovn_dbctl_main(int argc, char *argv[], const struct ovn_dbctl_options *); + +#endif /* ovn-dbctl.h */ diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index e3af0be926da..14840a8fa074 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -30,6 +30,7 @@ #include "lib/ovn-nb-idl.h" #include "lib/ovn-util.h" #include "memory.h" +#include "ovn-dbctl.h" #include "packets.h" #include "openvswitch/poll-loop.h" #include "process.h" @@ -48,83 +49,109 @@ VLOG_DEFINE_THIS_MODULE(nbctl); -/* --db: The database server to contact. */ -static const char *db; +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all? */ +static bool force_wait = false; -/* --oneline: Write each command's output as a single line? */ -static bool oneline; +static void +nbctl_add_base_prerequisites(struct ovsdb_idl *idl, + enum nbctl_wait_type wait_type) +{ + force_wait = false; -/* --dry-run: Do not commit any changes. */ -static bool dry_run; + ovsdb_idl_add_table(idl, &nbrec_table_nb_global); + if (wait_type == NBCTL_WAIT_SB) { + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg); + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg_timestamp); + } else if (wait_type == NBCTL_WAIT_HV) { + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg); + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg_timestamp); + } +} -/* --wait=TYPE: Wait for configuration change to take effect? */ -enum nbctl_wait_type { - NBCTL_WAIT_NONE, /* Do not wait. */ - NBCTL_WAIT_SB, /* Wait for southbound database updates. */ - NBCTL_WAIT_HV /* Wait for hypervisors to catch up. */ -}; -static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; +static void +nbctl_pre_execute(struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn, + enum nbctl_wait_type wait_type) +{ + const struct nbrec_nb_global *nb = nbrec_nb_global_first(idl); + if (!nb) { + /* XXX add verification that table is empty */ + nb = nbrec_nb_global_insert(txn); + } -static bool print_wait_time = false; + /* Deal with potential overflows. */ + if (nb->nb_cfg == LLONG_MAX) { + nbrec_nb_global_set_nb_cfg(nb, 0); + } -/* Should we wait (if specified by 'wait_type') even if the commands don't - * change the database at all? */ -static bool force_wait = false; + if (wait_type != NBCTL_WAIT_NONE) { + ovsdb_idl_txn_increment(txn, &nb->header_, &nbrec_nb_global_col_nb_cfg, + force_wait); + } +} + +static char * +nbctl_post_execute(struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn, + enum ovsdb_idl_txn_status status, + enum nbctl_wait_type wait_type, + const struct timer *wait_timeout, long long int start_time, + bool print_wait_time) +{ + if (wait_type == NBCTL_WAIT_NONE) { + if (force_wait) { + VLOG_INFO("\"sync\" command has no effect without --wait"); + } + return NULL; + } + if (status == TXN_UNCHANGED) { + return NULL; + } + + ovs_assert(status == TXN_SUCCESS); + int64_t next_cfg = ovsdb_idl_txn_get_increment_new_value(txn); + ovsdb_idl_enable_reconnect(idl); + for (;;) { + ovsdb_idl_run(idl); + + const struct nbrec_nb_global *nb; + NBREC_NB_GLOBAL_FOR_EACH (nb, idl) { + int64_t cur_cfg = (wait_type == NBCTL_WAIT_SB + ? nb->sb_cfg + : MIN(nb->sb_cfg, nb->hv_cfg)); + if (cur_cfg >= next_cfg) { + if (print_wait_time) { + printf("Time spent on processing nb_cfg %"PRId64":\n", + next_cfg); + + long long int nb_timestamp = nb->nb_cfg_timestamp; + long long int sb_timestamp = nb->sb_cfg_timestamp; + long long int hv_timestamp = nb->hv_cfg_timestamp; + printf("\tovn-northd delay before processing:" + "\t%lldms\n", nb_timestamp - start_time); + printf("\tovn-northd completion:" + "\t\t\t%lldms\n", sb_timestamp - start_time); + if (wait_type == NBCTL_WAIT_HV) { + printf("\tovn-controller(s) completion:" + "\t\t%lldms\n", hv_timestamp - start_time); + } + } + return NULL; + } + } + ovsdb_idl_wait(idl); + if (wait_timeout) { + timer_wait(wait_timeout); + } + poll_block(); + if (wait_timeout && timer_expired(wait_timeout)) { + return xstrdup("timeout expired"); + } + } +} -/* --timeout: Time to wait for a connection to 'db'. */ -static unsigned int timeout; - -/* Format for table output. */ -static struct table_style table_style = TABLE_STYLE_DEFAULT; - -/* The IDL we're using and the current transaction, if any. - * This is for use by nbctl_exit() only, to allow it to clean up. - * Other code should use its context arguments. */ -static struct ovsdb_idl *the_idl; -static struct ovsdb_idl_txn *the_idl_txn; -OVS_NO_RETURN static void nbctl_exit(int status); - -/* --leader-only, --no-leader-only: Only accept the leader in a cluster. */ -static int leader_only = true; - -/* --shuffle-remotes, --no-shuffle-remotes: Shuffle the order of remotes that - * are specified in the connetion method string. */ -static int shuffle_remotes = true; - -/* --unixctl-path: Path to use for unixctl server socket, for daemon mode. */ -static char *unixctl_path; - -static unixctl_cb_func server_cmd_exit; -static unixctl_cb_func server_cmd_run; - -static void nbctl_cmd_init(void); -OVS_NO_RETURN static void usage(void); -static struct option *get_all_options(void); -static bool has_option(const struct ovs_cmdl_parsed_option *, size_t n, - int option); -static void nbctl_client(const char *socket_name, - const struct ovs_cmdl_parsed_option *, size_t n, - int argc, char *argv[]); -static bool will_detach(const struct ovs_cmdl_parsed_option *, size_t n); -static void apply_options_direct(const struct ovs_cmdl_parsed_option *, - size_t n, struct shash *local_options); -static char * OVS_WARN_UNUSED_RESULT run_prerequisites(struct ctl_command[], - size_t n_commands, - struct ovsdb_idl *); -static char * OVS_WARN_UNUSED_RESULT do_nbctl(const char *args, - struct ctl_command *, size_t n, - struct ovsdb_idl *, - const struct timer *, - bool *retry); static char * OVS_WARN_UNUSED_RESULT dhcp_options_get( struct ctl_context *ctx, const char *id, bool must_exist, const struct nbrec_dhcp_options **); -static char * OVS_WARN_UNUSED_RESULT main_loop(const char *args, - struct ctl_command *commands, - size_t n_commands, - struct ovsdb_idl *idl, - const struct timer *); -static void server_loop(struct ovsdb_idl *idl, int argc, char *argv[]); /* A context for keeping track of which switch/router certain ports are * connected to. @@ -134,35 +161,41 @@ static void server_loop(struct ovsdb_idl *idl, int argc, char *argv[]); * until transaction is committed and updates received from the server. */ struct nbctl_context { struct ctl_context base; + + bool context_valid; struct shash lsp_to_ls_map; struct shash lrp_to_lr_map; - bool context_valid; }; -static void -nbctl_context_init(struct nbctl_context *nbctx) +static struct ctl_context * +nbctl_ctx_create(void) { - nbctx->context_valid = false; - shash_init(&nbctx->lsp_to_ls_map); - shash_init(&nbctx->lrp_to_lr_map); + struct nbctl_context *nbctx = xmalloc(sizeof *nbctx); + *nbctx = (struct nbctl_context) { + .context_valid = false, + .lsp_to_ls_map = SHASH_INITIALIZER(&nbctx->lsp_to_ls_map), + .lrp_to_lr_map = SHASH_INITIALIZER(&nbctx->lrp_to_lr_map), + }; + return &nbctx->base; } static void -nbctl_context_destroy(struct nbctl_context *nbctx) +nbctl_ctx_destroy(struct ctl_context *base) { + struct nbctl_context *nbctx + = CONTAINER_OF(base, struct nbctl_context, base); nbctx->context_valid = false; shash_destroy(&nbctx->lsp_to_ls_map); shash_destroy(&nbctx->lrp_to_lr_map); + free(nbctx); } /* Casts 'base' into 'struct nbctl_context' and initializes it if needed. */ static struct nbctl_context * nbctl_context_get(struct ctl_context *base) { - struct nbctl_context *nbctx; - - nbctx = CONTAINER_OF(base, struct nbctl_context, base); - + struct nbctl_context *nbctx + = CONTAINER_OF(base, struct nbctl_context, base); if (nbctx->context_valid) { return nbctx; } @@ -185,466 +218,8 @@ nbctl_context_get(struct ctl_context *base) return nbctx; } -int -main(int argc, char *argv[]) -{ - struct ovsdb_idl *idl; - struct shash local_options; - - ovn_set_program_name(argv[0]); - fatal_ignore_sigpipe(); - vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN); - vlog_set_levels_from_string_assert("reconnect:warn"); - - nbctl_cmd_init(); - - /* Check if options are set via env var. */ - char **argv_ = ovs_cmdl_env_parse_all(&argc, argv, - getenv("OVN_NBCTL_OPTIONS")); - - /* ovn-nbctl has three operation modes: - * - * - Direct: Executes commands by contacting ovsdb-server directly. - * - * - Server: Runs in the background as a daemon waiting for requests - * from ovn-nbctl running in client mode. - * - * - Client: Executes commands by passing them to an ovn-nbctl running - * in the server mode. - * - * At this point we don't know what mode we're running in. The mode partly - * depends on the command line. So, for now we transform the command line - * into a parsed form, and figure out what to do with it later. - */ - struct ovs_cmdl_parsed_option *parsed_options; - size_t n_parsed_options; - char *error_s = ovs_cmdl_parse_all(argc, argv_, get_all_options(), - &parsed_options, &n_parsed_options); - if (error_s) { - ctl_fatal("%s", error_s); - } - - /* Now figure out the operation mode: - * - * - A --detach option implies server mode. - * - * - An OVN_NB_DAEMON environment variable implies client mode. - * - * - Otherwise, we're in direct mode. */ - char *socket_name = unixctl_path ?: getenv("OVN_NB_DAEMON"); - if (((socket_name && socket_name[0]) - || has_option(parsed_options, n_parsed_options, 'u')) - && !will_detach(parsed_options, n_parsed_options)) { - nbctl_client(socket_name, parsed_options, n_parsed_options, - argc, argv_); - } - - /* Parse command line. */ - shash_init(&local_options); - apply_options_direct(parsed_options, n_parsed_options, &local_options); - free(parsed_options); - - bool daemon_mode = false; - if (get_detach()) { - if (argc != optind) { - ctl_fatal("non-option arguments not supported with --detach " - "(use --help for help)"); - } - daemon_mode = true; - } - /* Initialize IDL. */ - idl = the_idl = ovsdb_idl_create_unconnected(&nbrec_idl_class, true); - ovsdb_idl_set_shuffle_remotes(idl, shuffle_remotes); - /* "retry" is true iff in daemon mode. */ - ovsdb_idl_set_remote(idl, db, daemon_mode); - ovsdb_idl_set_leader_only(idl, leader_only); - - if (daemon_mode) { - server_loop(idl, argc, argv_); - } else { - struct ctl_command *commands; - size_t n_commands; - char *error; - - error = ctl_parse_commands(argc - optind, argv_ + optind, - &local_options, &commands, &n_commands); - if (error) { - ctl_fatal("%s", error); - } - - char *args = process_escape_args(argv_); - VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG, - "Called as %s", args); - - ctl_timeout_setup(timeout); - - error = run_prerequisites(commands, n_commands, idl); - if (error) { - goto cleanup; - } - - error = main_loop(args, commands, n_commands, idl, NULL); - -cleanup: - free(args); - - struct ctl_command *c; - for (c = commands; c < &commands[n_commands]; c++) { - ds_destroy(&c->output); - table_destroy(c->table); - free(c->table); - shash_destroy_free_data(&c->options); - } - free(commands); - if (error) { - ctl_fatal("%s", error); - } - } - - ovsdb_idl_destroy(idl); - idl = the_idl = NULL; - - for (int i = 0; i < argc; i++) { - free(argv_[i]); - } - free(argv_); - exit(EXIT_SUCCESS); -} - -static char * -main_loop(const char *args, struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl, const struct timer *wait_timeout) -{ - unsigned int seqno; - bool idl_ready; - - /* Execute the commands. - * - * 'seqno' is the database sequence number for which we last tried to - * execute our transaction. There's no point in trying to commit more than - * once for any given sequence number, because if the transaction fails - * it's because the database changed and we need to obtain an up-to-date - * view of the database before we try the transaction again. */ - seqno = ovsdb_idl_get_seqno(idl); - - /* IDL might have already obtained the database copy during previous - * invocation. If so, we can't expect the sequence number to change before - * we issue any new requests. */ - idl_ready = ovsdb_idl_has_ever_connected(idl); - for (;;) { - ovsdb_idl_run(idl); - if (!ovsdb_idl_is_alive(idl)) { - int retval = ovsdb_idl_get_last_error(idl); - ctl_fatal("%s: database connection failed (%s)", - db, ovs_retval_to_string(retval)); - } - - if (idl_ready || seqno != ovsdb_idl_get_seqno(idl)) { - idl_ready = false; - seqno = ovsdb_idl_get_seqno(idl); - - bool retry; - char *error = do_nbctl(args, commands, n_commands, idl, - wait_timeout, &retry); - if (error) { - return error; - } - if (!retry) { - return NULL; - } - } - - if (seqno == ovsdb_idl_get_seqno(idl)) { - ovsdb_idl_wait(idl); - poll_block(); - } - } - - return NULL; -} - -/* All options that affect the main loop and are not external. */ -#define MAIN_LOOP_OPTION_ENUMS \ - OPT_NO_WAIT, \ - OPT_WAIT, \ - OPT_PRINT_WAIT_TIME, \ - OPT_DRY_RUN, \ - OPT_ONELINE - -#define MAIN_LOOP_LONG_OPTIONS \ - {"no-wait", no_argument, NULL, OPT_NO_WAIT}, \ - {"wait", required_argument, NULL, OPT_WAIT}, \ - {"print-wait-time", no_argument, NULL, OPT_PRINT_WAIT_TIME}, \ - {"dry-run", no_argument, NULL, OPT_DRY_RUN}, \ - {"oneline", no_argument, NULL, OPT_ONELINE}, \ - {"timeout", required_argument, NULL, 't'} - -enum { - OPT_DB = UCHAR_MAX + 1, - OPT_NO_SYSLOG, - OPT_LOCAL, - OPT_COMMANDS, - OPT_OPTIONS, - OPT_LEADER_ONLY, - OPT_NO_LEADER_ONLY, - OPT_SHUFFLE_REMOTES, - OPT_NO_SHUFFLE_REMOTES, - OPT_BOOTSTRAP_CA_CERT, - MAIN_LOOP_OPTION_ENUMS, - OVN_DAEMON_OPTION_ENUMS, - VLOG_OPTION_ENUMS, - TABLE_OPTION_ENUMS, - SSL_OPTION_ENUMS, -}; - -static char * OVS_WARN_UNUSED_RESULT -handle_main_loop_option(int opt, const char *arg, bool *handled) -{ - ovs_assert(handled); - *handled = true; - - switch (opt) { - case OPT_ONELINE: - oneline = true; - break; - - case OPT_NO_WAIT: - wait_type = NBCTL_WAIT_NONE; - break; - - case OPT_WAIT: - if (!strcmp(arg, "none")) { - wait_type = NBCTL_WAIT_NONE; - } else if (!strcmp(arg, "sb")) { - wait_type = NBCTL_WAIT_SB; - } else if (!strcmp(arg, "hv")) { - wait_type = NBCTL_WAIT_HV; - } else { - return xstrdup("argument to --wait must be " - "\"none\", \"sb\", or \"hv\""); - } - break; - - case OPT_PRINT_WAIT_TIME: - print_wait_time = true; - break; - - case OPT_DRY_RUN: - dry_run = true; - break; - - case 't': - if (!str_to_uint(arg, 10, &timeout) || !timeout) { - return xasprintf("value %s on -t or --timeout is invalid", arg); - } - break; - - default: - *handled = false; - break; - } - - return NULL; -} - -static char * OVS_WARN_UNUSED_RESULT -build_short_options(const struct option *long_options, bool print_errors) -{ - char *tmp, *short_options; - - tmp = ovs_cmdl_long_options_to_short_options(long_options); - short_options = xasprintf("+%s%s", print_errors ? "" : ":", tmp); - free(tmp); - - return short_options; -} - -static struct option * OVS_WARN_UNUSED_RESULT -append_command_options(const struct option *options, int opt_val) -{ - struct option *o; - size_t n_allocated; - size_t n_existing; - int i; - - for (i = 0; options[i].name; i++) { - ; - } - n_allocated = i + 1; - n_existing = i; - - /* We want to parse both global and command-specific options here, but - * getopt_long() isn't too convenient for the job. We copy our global - * options into a dynamic array, then append all of the command-specific - * options. */ - o = xmemdup(options, n_allocated * sizeof *options); - ctl_add_cmd_options(&o, &n_existing, &n_allocated, opt_val); - - return o; -} - -static struct option * -get_all_options(void) -{ - static const struct option global_long_options[] = { - {"db", required_argument, NULL, OPT_DB}, - {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, - {"help", no_argument, NULL, 'h'}, - {"commands", no_argument, NULL, OPT_COMMANDS}, - {"options", no_argument, NULL, OPT_OPTIONS}, - {"leader-only", no_argument, NULL, OPT_LEADER_ONLY}, - {"no-leader-only", no_argument, NULL, OPT_NO_LEADER_ONLY}, - {"shuffle-remotes", no_argument, NULL, OPT_SHUFFLE_REMOTES}, - {"no-shuffle-remotes", no_argument, NULL, OPT_NO_SHUFFLE_REMOTES}, - {"version", no_argument, NULL, 'V'}, - {"unixctl", required_argument, NULL, 'u'}, - MAIN_LOOP_LONG_OPTIONS, - OVN_DAEMON_LONG_OPTIONS, - VLOG_LONG_OPTIONS, - STREAM_SSL_LONG_OPTIONS, - {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, - TABLE_LONG_OPTIONS, - {NULL, 0, NULL, 0}, - }; - - static struct option *options; - if (!options) { - options = append_command_options(global_long_options, OPT_LOCAL); - } - - return options; -} - -static bool -has_option(const struct ovs_cmdl_parsed_option *parsed_options, size_t n, - int option) -{ - for (const struct ovs_cmdl_parsed_option *po = parsed_options; - po < &parsed_options[n]; po++) { - if (po->o->val == option) { - return true; - } - } - return false; -} - -static bool -will_detach(const struct ovs_cmdl_parsed_option *parsed_options, size_t n) -{ - return has_option(parsed_options, n, OVN_OPT_DETACH); -} - -static char * OVS_WARN_UNUSED_RESULT -add_local_option(const char *name, const char *arg, - struct shash *local_options) -{ - char *full_name = xasprintf("--%s", name); - if (shash_find(local_options, full_name)) { - char *error = xasprintf("'%s' option specified multiple times", - full_name); - free(full_name); - return error; - } - shash_add_nocopy(local_options, full_name, nullable_xstrdup(arg)); - return NULL; -} - -static void -apply_options_direct(const struct ovs_cmdl_parsed_option *parsed_options, - size_t n, struct shash *local_options) -{ - for (const struct ovs_cmdl_parsed_option *po = parsed_options; - po < &parsed_options[n]; po++) { - bool handled; - char *error = handle_main_loop_option(po->o->val, po->arg, &handled); - if (error) { - ctl_fatal("%s", error); - } - if (handled) { - continue; - } - - optarg = po->arg; - switch (po->o->val) { - case OPT_DB: - db = po->arg; - break; - - case OPT_NO_SYSLOG: - vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); - break; - - case OPT_LOCAL: - error = add_local_option(po->o->name, po->arg, local_options); - if (error) { - ctl_fatal("%s", error); - } - break; - - case 'h': - usage(); - exit(EXIT_SUCCESS); - - case OPT_COMMANDS: - ctl_print_commands(); - /* fall through */ - - case OPT_OPTIONS: - ctl_print_options(get_all_options()); - /* fall through */ - - case OPT_LEADER_ONLY: - leader_only = true; - break; - - case OPT_NO_LEADER_ONLY: - leader_only = false; - break; - - case OPT_SHUFFLE_REMOTES: - shuffle_remotes = true; - break; - - case OPT_NO_SHUFFLE_REMOTES: - shuffle_remotes = false; - break; - - case 'u': - unixctl_path = optarg; - break; - - case 'V': - ovn_print_version(0, 0); - printf("DB Schema %s\n", nbrec_get_db_version()); - exit(EXIT_SUCCESS); - - OVN_DAEMON_OPTION_HANDLERS - VLOG_OPTION_HANDLERS - TABLE_OPTION_HANDLERS(&table_style) - STREAM_SSL_OPTION_HANDLERS - - case OPT_BOOTSTRAP_CA_CERT: - stream_ssl_set_ca_cert_file(po->arg, true); - break; - - case '?': - exit(EXIT_FAILURE); - - default: - abort(); - - case 0: - break; - } - } - - if (!db) { - db = default_nb_db(); - } -} - static void -usage(void) +nbctl_usage(void) { printf("\ %s: OVN northbound DB management utility\n\ @@ -1212,13 +787,9 @@ nbctl_init(struct ctl_context *ctx OVS_UNUSED) } static void -nbctl_pre_sync(struct ctl_context *ctx OVS_UNUSED) +nbctl_pre_sync(struct ctl_context *base OVS_UNUSED) { - if (wait_type != NBCTL_WAIT_NONE) { - force_wait = true; - } else { - VLOG_INFO("\"sync\" command has no effect without --wait"); - } + force_wait = true; } static void @@ -6208,305 +5779,6 @@ static const struct ctl_table_class tables[NBREC_N_TABLES] = { = {&nbrec_connection_col_target, NULL, NULL}, }; -static char * -run_prerequisites(struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl) -{ - ovsdb_idl_add_table(idl, &nbrec_table_nb_global); - if (wait_type == NBCTL_WAIT_SB) { - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg); - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg_timestamp); - } else if (wait_type == NBCTL_WAIT_HV) { - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg); - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg_timestamp); - } - - for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) { - if (c->syntax->prerequisites) { - struct ctl_context ctx; - - ds_init(&c->output); - c->table = NULL; - - ctl_context_init(&ctx, c, idl, NULL, NULL, NULL); - (c->syntax->prerequisites)(&ctx); - if (ctx.error) { - char *error = xstrdup(ctx.error); - ctl_context_done(&ctx, c); - return error; - } - ctl_context_done(&ctx, c); - - ovs_assert(!c->output.string); - ovs_assert(!c->table); - } - } - - return NULL; -} - -static void -oneline_format(struct ds *lines, struct ds *s) -{ - size_t j; - - ds_chomp(lines, '\n'); - for (j = 0; j < lines->length; j++) { - int ch = lines->string[j]; - switch (ch) { - case '\n': - ds_put_cstr(s, "\\n"); - break; - - case '\\': - ds_put_cstr(s, "\\\\"); - break; - - default: - ds_put_char(s, ch); - } - } - ds_put_char(s, '\n'); -} - -static void -oneline_print(struct ds *lines) -{ - struct ds s = DS_EMPTY_INITIALIZER; - oneline_format(lines, &s); - fputs(ds_cstr(&s), stdout); - ds_destroy(&s); -} - -static char * -do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl, const struct timer *wait_timeout, bool *retry) -{ - struct ovsdb_idl_txn *txn; - enum ovsdb_idl_txn_status status; - struct ovsdb_symbol_table *symtab; - struct nbctl_context ctx; - struct ctl_command *c; - struct shash_node *node; - int64_t next_cfg = 0; - char *error = NULL; - int64_t start_time = 0; - - ovs_assert(retry); - - txn = the_idl_txn = ovsdb_idl_txn_create(idl); - if (dry_run) { - ovsdb_idl_txn_set_dry_run(txn); - } - - ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args); - - const struct nbrec_nb_global *nb = nbrec_nb_global_first(idl); - if (!nb) { - /* XXX add verification that table is empty */ - nb = nbrec_nb_global_insert(txn); - } - - /* Deal with potential overflows. */ - if (nb->nb_cfg == LLONG_MAX) { - nbrec_nb_global_set_nb_cfg(nb, 0); - } - - if (wait_type != NBCTL_WAIT_NONE) { - ovsdb_idl_txn_increment(txn, &nb->header_, &nbrec_nb_global_col_nb_cfg, - force_wait); - } - - symtab = ovsdb_symbol_table_create(); - for (c = commands; c < &commands[n_commands]; c++) { - ds_init(&c->output); - c->table = NULL; - } - nbctl_context_init(&ctx); - ctl_context_init(&ctx.base, NULL, idl, txn, symtab, NULL); - for (c = commands; c < &commands[n_commands]; c++) { - ctl_context_init_command(&ctx.base, c); - if (c->syntax->run) { - (c->syntax->run)(&ctx.base); - } - if (ctx.base.error) { - error = xstrdup(ctx.base.error); - ctl_context_done(&ctx.base, c); - goto out_error; - } - ctl_context_done_command(&ctx.base, c); - - if (ctx.base.try_again) { - ctl_context_done(&ctx.base, NULL); - goto try_again; - } - } - ctl_context_done(&ctx.base, NULL); - - SHASH_FOR_EACH (node, &symtab->sh) { - struct ovsdb_symbol *symbol = node->data; - if (!symbol->created) { - error = xasprintf("row id \"%s\" is referenced but never created " - "(e.g. with \"-- --id=%s create ...\")", - node->name, node->name); - goto out_error; - } - if (!symbol->strong_ref) { - if (!symbol->weak_ref) { - VLOG_WARN("row id \"%s\" was created but no reference to it " - "was inserted, so it will not actually appear in " - "the database", node->name); - } else { - VLOG_WARN("row id \"%s\" was created but only a weak " - "reference to it was inserted, so it will not " - "actually appear in the database", node->name); - } - } - } - - start_time = time_wall_msec(); - status = ovsdb_idl_txn_commit_block(txn); - if (wait_type != NBCTL_WAIT_NONE && status == TXN_SUCCESS) { - next_cfg = ovsdb_idl_txn_get_increment_new_value(txn); - } - if (status == TXN_UNCHANGED || status == TXN_SUCCESS) { - for (c = commands; c < &commands[n_commands]; c++) { - if (c->syntax->postprocess) { - ctl_context_init(&ctx.base, c, idl, txn, symtab, NULL); - (c->syntax->postprocess)(&ctx.base); - if (ctx.base.error) { - error = xstrdup(ctx.base.error); - ctl_context_done(&ctx.base, c); - goto out_error; - } - ctl_context_done(&ctx.base, c); - } - } - } - - switch (status) { - case TXN_UNCOMMITTED: - case TXN_INCOMPLETE: - OVS_NOT_REACHED(); - - case TXN_ABORTED: - /* Should not happen--we never call ovsdb_idl_txn_abort(). */ - error = xstrdup("transaction aborted"); - goto out_error; - - case TXN_UNCHANGED: - case TXN_SUCCESS: - break; - - case TXN_TRY_AGAIN: - goto try_again; - - case TXN_ERROR: - error = xasprintf("transaction error: %s", - ovsdb_idl_txn_get_error(txn)); - goto out_error; - - case TXN_NOT_LOCKED: - /* Should not happen--we never call ovsdb_idl_set_lock(). */ - error = xstrdup("database not locked"); - goto out_error; - - default: - OVS_NOT_REACHED(); - } - - for (c = commands; c < &commands[n_commands]; c++) { - struct ds *ds = &c->output; - - if (c->table) { - table_print(c->table, &table_style); - } else if (oneline) { - oneline_print(ds); - } else { - fputs(ds_cstr(ds), stdout); - } - } - - if (wait_type != NBCTL_WAIT_NONE && status != TXN_UNCHANGED) { - ovsdb_idl_enable_reconnect(idl); - for (;;) { - ovsdb_idl_run(idl); - NBREC_NB_GLOBAL_FOR_EACH (nb, idl) { - int64_t cur_cfg = (wait_type == NBCTL_WAIT_SB - ? nb->sb_cfg - : MIN(nb->sb_cfg, nb->hv_cfg)); - if (cur_cfg >= next_cfg) { - if (print_wait_time) { - printf("Time spent on processing nb_cfg %"PRId64":\n", - next_cfg); - printf("\tovn-northd delay before processing:" - "\t%"PRId64"ms\n", - nb->nb_cfg_timestamp - start_time); - printf("\tovn-northd completion:" - "\t\t\t%"PRId64"ms\n", - nb->sb_cfg_timestamp - start_time); - if (wait_type == NBCTL_WAIT_HV) { - printf("\tovn-controller(s) completion:" - "\t\t%"PRId64"ms\n", - nb->hv_cfg_timestamp - start_time); - } - } - goto done; - } - } - ovsdb_idl_wait(idl); - if (wait_timeout) { - timer_wait(wait_timeout); - } - poll_block(); - if (wait_timeout && timer_expired(wait_timeout)) { - error = xstrdup("timeout expired"); - goto out_error; - } - } - done: ; - } - - nbctl_context_destroy(&ctx); - ovsdb_symbol_table_destroy(symtab); - ovsdb_idl_txn_destroy(txn); - the_idl_txn = NULL; - - *retry = false; - return NULL; - -try_again: - /* Our transaction needs to be rerun, or a prerequisite was not met. Free - * resources and return so that the caller can try again. */ - *retry = true; - -out_error: - ovsdb_idl_txn_abort(txn); - ovsdb_idl_txn_destroy(txn); - the_idl_txn = NULL; - - nbctl_context_destroy(&ctx); - ovsdb_symbol_table_destroy(symtab); - return error; -} - -/* Frees the current transaction and the underlying IDL and then calls - * exit(status). - * - * Freeing the transaction and the IDL is not strictly necessary, but it makes - * for a clean memory leak report from valgrind in the normal case. That makes - * it easier to notice real memory leaks. */ -static void -nbctl_exit(int status) -{ - if (the_idl_txn) { - ovsdb_idl_txn_abort(the_idl_txn); - ovsdb_idl_txn_destroy(the_idl_txn); - } - ovsdb_idl_destroy(the_idl); - exit(status); -} - static const struct ctl_command_syntax nbctl_commands[] = { { "init", 0, 0, "", NULL, nbctl_init, NULL, "", RW }, { "sync", 0, 0, "", nbctl_pre_sync, nbctl_sync, NULL, "", RO }, @@ -6708,401 +5980,29 @@ static const struct ctl_command_syntax nbctl_commands[] = { {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO}, }; -/* Registers nbctl and common db commands. */ -static void -nbctl_cmd_init(void) +int +main(int argc, char *argv[]) { - ctl_init(&nbrec_idl_class, nbrec_table_classes, tables, NULL, nbctl_exit); - ctl_register_commands(nbctl_commands); -} - -/* Server implementation. */ + struct ovn_dbctl_options dbctl_options = { + .db_version = nbrec_get_db_version(), + .default_db = default_nb_db(), -#undef ctl_fatal + .options_env_var_name = "OVN_NBCTL_OPTIONS", + .daemon_env_var_name = "OVN_NB_DAEMON", -static const struct option * -find_option_by_value(const struct option *options, int value) -{ - const struct option *o; + .idl_class = &nbrec_idl_class, + .tables = tables, + .cmd_show_table = NULL, + .commands = nbctl_commands, - for (o = options; o->name; o++) { - if (o->val == value) { - return o; - } - } - return NULL; -} + .usage = nbctl_usage, + .add_base_prerequisites = nbctl_add_base_prerequisites, + .pre_execute = nbctl_pre_execute, + .post_execute = nbctl_post_execute, -static char * OVS_WARN_UNUSED_RESULT -server_parse_options(int argc, char *argv[], struct shash *local_options, - int *n_options_p) -{ - static const struct option global_long_options[] = { - VLOG_LONG_OPTIONS, - MAIN_LOOP_LONG_OPTIONS, - TABLE_LONG_OPTIONS, - {NULL, 0, NULL, 0}, + .ctx_create = nbctl_ctx_create, + .ctx_destroy = nbctl_ctx_destroy, }; - const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1; - char *short_options; - struct option *options; - char *error = NULL; - - ovs_assert(n_options_p); - - short_options = build_short_options(global_long_options, false); - options = append_command_options(global_long_options, OPT_LOCAL); - - optind = 0; - opterr = 0; - for (;;) { - int idx; - int c; - - c = getopt_long(argc, argv, short_options, options, &idx); - if (c == -1) { - break; - } - - bool handled; - error = handle_main_loop_option(c, optarg, &handled); - if (error) { - goto out; - } - if (handled) { - continue; - } - - switch (c) { - case OPT_LOCAL: - error = add_local_option(options[idx].name, optarg, local_options); - if (error) { - goto out; - } - break; - - VLOG_OPTION_HANDLERS - TABLE_OPTION_HANDLERS(&table_style) - - case '?': - if (find_option_by_value(options, optopt)) { - error = xasprintf("option '%s' doesn't allow an argument", - argv[optind-1]); - } else if (optopt) { - error = xasprintf("unrecognized option '%c'", optopt); - } else { - error = xasprintf("unrecognized option '%s'", argv[optind-1]); - } - goto out; - break; - - case ':': - error = xasprintf("option '%s' requires an argument", - argv[optind-1]); - goto out; - break; - - case 0: - break; - - default: - error = xasprintf("unhandled option '%c'", c); - goto out; - break; - } - } - *n_options_p = optind; - -out: - for (int i = n_global_long_options; options[i].name; i++) { - free(CONST_CAST(char *, options[i].name)); - } - free(options); - free(short_options); - - return error; -} - -static void -server_cmd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *exiting_) -{ - bool *exiting = exiting_; - *exiting = true; - unixctl_command_reply(conn, NULL); -} - -static void -server_cmd_run(struct unixctl_conn *conn, int argc, const char **argv_, - void *idl_) -{ - struct ovsdb_idl *idl = idl_; - struct ctl_command *commands = NULL; - struct shash local_options; - size_t n_commands = 0; - int n_options = 0; - char *error = NULL; - - /* Copy args so that getopt() can permute them. Leave last entry NULL. */ - char **argv = xcalloc(argc + 1, sizeof *argv); - for (int i = 0; i < argc; i++) { - argv[i] = xstrdup(argv_[i]); - } - - /* Reset global state. */ - oneline = false; - dry_run = false; - wait_type = NBCTL_WAIT_NONE; - force_wait = false; - timeout = 0; - table_style = table_style_default; - - /* Parse commands & options. */ - char *args = process_escape_args(argv); - shash_init(&local_options); - error = server_parse_options(argc, argv, &local_options, &n_options); - if (error) { - unixctl_command_reply_error(conn, error); - goto out; - } - error = ctl_parse_commands(argc - n_options, argv + n_options, - &local_options, &commands, &n_commands); - if (error) { - unixctl_command_reply_error(conn, error); - goto out; - } - VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG, - "Running command %s", args); - - struct timer *wait_timeout = NULL; - struct timer wait_timeout_; - if (timeout) { - wait_timeout = &wait_timeout_; - timer_set_duration(wait_timeout, timeout * 1000); - } - - error = run_prerequisites(commands, n_commands, idl); - if (error) { - unixctl_command_reply_error(conn, error); - goto out; - } - error = main_loop(args, commands, n_commands, idl, wait_timeout); - if (error) { - unixctl_command_reply_error(conn, error); - goto out; - } - - struct ds output = DS_EMPTY_INITIALIZER; - table_format_reset(); - for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) { - if (c->table) { - table_format(c->table, &table_style, &output); - } else if (oneline) { - oneline_format(&c->output, &output); - } else { - ds_put_cstr(&output, ds_cstr_ro(&c->output)); - } - } - unixctl_command_reply(conn, ds_cstr_ro(&output)); - ds_destroy(&output); - -out: - free(error); - - struct ctl_command *c; - for (c = commands; c < &commands[n_commands]; c++) { - ds_destroy(&c->output); - table_destroy(c->table); - free(c->table); - shash_destroy_free_data(&c->options); - } - free(commands); - shash_destroy_free_data(&local_options); - free(args); - for (int i = 0; i < argc; i++) { - free(argv[i]); - } - free(argv); -} - -static void -server_cmd_init(struct ovsdb_idl *idl, bool *exiting) -{ - unixctl_command_register("exit", "", 0, 0, server_cmd_exit, exiting); - unixctl_command_register("run", "", 0, INT_MAX, server_cmd_run, idl); -} - -static void -server_loop(struct ovsdb_idl *idl, int argc, char *argv[]) -{ - struct unixctl_server *server = NULL; - bool exiting = false; - - service_start(&argc, &argv); - daemonize_start(false); - - char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path); - int error = unixctl_server_create(abs_unixctl_path, &server); - free(abs_unixctl_path); - - if (error) { - ctl_fatal("failed to create unixctl server (%s)", - ovs_retval_to_string(error)); - } - puts(unixctl_server_get_path(server)); - fflush(stdout); - server_cmd_init(idl, &exiting); - - for (;;) { - memory_run(); - if (memory_should_report()) { - struct simap usage = SIMAP_INITIALIZER(&usage); - - /* Nothing special to report yet. */ - memory_report(&usage); - simap_destroy(&usage); - } - - ovsdb_idl_run(idl); - if (!ovsdb_idl_is_alive(idl)) { - int retval = ovsdb_idl_get_last_error(idl); - ctl_fatal("%s: database connection failed (%s)", - db, ovs_retval_to_string(retval)); - } - - if (ovsdb_idl_has_ever_connected(idl)) { - daemonize_complete(); - } - unixctl_server_run(server); - - if (exiting) { - break; - } - - memory_wait(); - ovsdb_idl_wait(idl); - unixctl_server_wait(server); - poll_block(); - } - - unixctl_server_destroy(server); -} - -static void -nbctl_client(const char *socket_name, - const struct ovs_cmdl_parsed_option *parsed_options, size_t n, - int argc, char *argv[]) -{ - struct svec args = SVEC_EMPTY_INITIALIZER; - - for (const struct ovs_cmdl_parsed_option *po = parsed_options; - po < &parsed_options[n]; po++) { - optarg = po->arg; - switch (po->o->val) { - case OPT_DB: - VLOG_WARN("not using ovn-nbctl daemon because of %s option", - po->o->name); - svec_destroy(&args); - return; - - case OPT_NO_SYSLOG: - vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); - break; - - case 'h': - usage(); - exit(EXIT_SUCCESS); - - case OPT_COMMANDS: - ctl_print_commands(); - /* fall through */ - - case OPT_OPTIONS: - ctl_print_options(get_all_options()); - /* fall through */ - - case OPT_LEADER_ONLY: - case OPT_NO_LEADER_ONLY: - case OPT_SHUFFLE_REMOTES: - case OPT_NO_SHUFFLE_REMOTES: - case OPT_BOOTSTRAP_CA_CERT: - STREAM_SSL_CASES - OVN_DAEMON_OPTION_CASES - VLOG_INFO("using ovn-nbctl daemon, ignoring %s option", - po->o->name); - break; - - case 'u': - socket_name = optarg; - break; - - case 'V': - ovs_print_version(0, 0); - printf("DB Schema %s\n", nbrec_get_db_version()); - exit(EXIT_SUCCESS); - case 't': - if (!str_to_uint(po->arg, 10, &timeout) || !timeout) { - ctl_fatal("value %s on -t or --timeout is invalid", po->arg); - } - break; - - VLOG_OPTION_HANDLERS - - case OPT_LOCAL: - default: - if (po->arg) { - svec_add_nocopy(&args, - xasprintf("--%s=%s", po->o->name, po->arg)); - } else { - svec_add_nocopy(&args, xasprintf("--%s", po->o->name)); - } - break; - } - } - - ovs_assert(socket_name && socket_name[0]); - - svec_add(&args, "--"); - for (int i = optind; i < argc; i++) { - svec_add(&args, argv[i]); - } - - ctl_timeout_setup(timeout); - - struct jsonrpc *client; - int error = unixctl_client_create(socket_name, &client); - if (error) { - ctl_fatal("%s: could not connect to ovn-nb daemon (%s); " - "unset OVN_NB_DAEMON to avoid using daemon", - socket_name, ovs_strerror(error)); - } - - char *cmd_result; - char *cmd_error; - error = unixctl_client_transact(client, "run", - args.n, args.names, - &cmd_result, &cmd_error); - if (error) { - ctl_fatal("%s: transaction error (%s)", - socket_name, ovs_strerror(error)); - } - svec_destroy(&args); - - int exit_status; - if (cmd_error) { - exit_status = EXIT_FAILURE; - fprintf(stderr, "%s: %s", program_name, cmd_error); - } else { - exit_status = EXIT_SUCCESS; - fputs(cmd_result, stdout); - } - free(cmd_result); - free(cmd_error); - jsonrpc_close(client); - for (int i = 0; i < argc; i++) { - free(argv[i]); - } - free(argv); - exit(exit_status); + return ovn_dbctl_main(argc, argv, &dbctl_options); } From patchwork Fri May 7 04:06:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475318 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxk00M4Fz9sPf for ; Fri, 7 May 2021 14:07:36 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 1B08B60AAA; Fri, 7 May 2021 04:07:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id l2ZFoRLWUXpv; Fri, 7 May 2021 04:07:32 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id B74B560E1F; Fri, 7 May 2021 04:07:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 8A34EC001C; Fri, 7 May 2021 04:07:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 50721C000F for ; Fri, 7 May 2021 04:07:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 9C238404CA for ; Fri, 7 May 2021 04:07:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6otS3kGek8GM for ; Fri, 7 May 2021 04:07:19 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 72F0C404BD for ; Fri, 7 May 2021 04:07:19 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id D04A2C0004; Fri, 7 May 2021 04:07:16 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:39 -0700 Message-Id: <20210507040659.26830-8-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 07/27] ovn-dbctl: Fix memory leak in client mode. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This isn't notable, since this commit frees it just before exiting, but it cleans up the Address Sanitizer report. Signed-off-by: Ben Pfaff --- utilities/ovn-dbctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c index 28ebc6267066..d815dc5c8c5f 100644 --- a/utilities/ovn-dbctl.c +++ b/utilities/ovn-dbctl.c @@ -1210,5 +1210,9 @@ dbctl_client(const struct ovn_dbctl_options *dbctl_options, free(cmd_result); free(cmd_error); jsonrpc_close(client); + for (int i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); exit(exit_status); } From patchwork Fri May 7 04:06:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475322 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxkT3WYhz9sPf for ; Fri, 7 May 2021 14:08:01 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 9693B61645; Fri, 7 May 2021 04:07:59 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tazEibV6mM2j; Fri, 7 May 2021 04:07:48 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTP id 1ED1D60A98; Fri, 7 May 2021 04:07:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D86CBC000E; Fri, 7 May 2021 04:07:42 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1FFABC000F for ; Fri, 7 May 2021 04:07:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 9079083D16 for ; Fri, 7 May 2021 04:07:26 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5wl79vBN60XT for ; Fri, 7 May 2021 04:07:21 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 0640D83D11 for ; Fri, 7 May 2021 04:07:20 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 3D8E1C0009; Fri, 7 May 2021 04:07:17 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:40 -0700 Message-Id: <20210507040659.26830-9-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 08/27] ovn-sbctl: Add daemon support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Also rewrite the manpage and convert it to XML for consistency with ovn-nbctl, and add tests. Signed-off-by: Ben Pfaff --- NEWS | 4 +- manpages.mk | 17 - tests/ovn-sbctl.at | 76 +++-- utilities/automake.mk | 7 +- utilities/ovn-dbctl.c | 24 +- utilities/ovn-dbctl.h | 3 +- utilities/ovn-nbctl.c | 1 + utilities/ovn-sbctl.8.in | 317 ------------------ utilities/ovn-sbctl.8.xml | 580 +++++++++++++++++++++++++++++++++ utilities/ovn-sbctl.c | 669 +++++++------------------------------- 10 files changed, 776 insertions(+), 922 deletions(-) delete mode 100644 utilities/ovn-sbctl.8.in create mode 100644 utilities/ovn-sbctl.8.xml diff --git a/NEWS b/NEWS index 0565a0975d6e..67c8b5f8bb38 100644 --- a/NEWS +++ b/NEWS @@ -16,7 +16,9 @@ Post-v21.03.0 be used in the logical flow matches. CMS can consider setting this to false, if they want to use smart NICs which don't support offloading datapath flows with this field used. - - ovn-nbctl daemon mode is no longer considered experimental. + - Utilities: + * ovn-nbctl daemon mode is no longer considered experimental. + * ovn-sbctl now also supports daemon mode. OVN v21.03.0 - 12 Mar 2021 ------------------------- diff --git a/manpages.mk b/manpages.mk index 44e544681424..3334b38f943d 100644 --- a/manpages.mk +++ b/manpages.mk @@ -10,20 +10,3 @@ lib/common-syn.man: lib/common.man: lib/ovs.tmac: -utilities/ovn-sbctl.8: \ - utilities/ovn-sbctl.8.in \ - lib/common.man \ - lib/db-ctl-base.man \ - lib/ovs.tmac \ - lib/ssl-bootstrap.man \ - lib/ssl.man \ - lib/table.man \ - lib/vlog.man -utilities/ovn-sbctl.8.in: -lib/common.man: -lib/db-ctl-base.man: -lib/ovs.tmac: -lib/ssl-bootstrap.man: -lib/ssl.man: -lib/table.man: -lib/vlog.man: diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at index 2712cc15490c..9334762fd313 100644 --- a/tests/ovn-sbctl.at +++ b/tests/ovn-sbctl.at @@ -1,9 +1,14 @@ AT_BANNER([ovn-sbctl]) +OVS_START_SHELL_HELPERS # OVN_SBCTL_TEST_START m4_define([OVN_SBCTL_TEST_START], - [dnl Create databases (ovn-nb, ovn-sb). - AT_KEYWORDS([ovn]) + [AT_KEYWORDS([ovn]) + AT_CAPTURE_FILE([ovsdb-server.log]) + AT_CAPTURE_FILE([ovn-northd.log]) + ovn_sbctl_test_start $1]) +ovn_sbctl_test_start() { + dnl Create databases (ovn-nb, ovn-sb). for daemon in ovn-nb ovn-sb; do AT_CHECK([ovsdb-tool create $daemon.db $abs_top_srcdir/${daemon}.ovsschema]) done @@ -15,27 +20,54 @@ m4_define([OVN_SBCTL_TEST_START], AT_CHECK([[sed < stderr ' /vlog|INFO|opened log file/d /ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']]) - AT_CAPTURE_FILE([ovsdb-server.log]) dnl Start ovn-northd. AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr]) on_exit "kill `cat ovn-northd.pid`" AT_CHECK([[sed < stderr ' /vlog|INFO|opened log file/d']]) - AT_CAPTURE_FILE([ovn-northd.log]) -]) + + AS_CASE([$1], + [daemon], + [export OVN_SB_DAEMON=$(ovn-sbctl --pidfile --detach --no-chdir --log-file -vsocket_util:off) + on_exit "kill `cat ovn-sbctl.pid`"], + [direct], [], + [*], [AT_FAIL_IF(:)]) +} # OVN_SBCTL_TEST_STOP -m4_define([OVN_SBCTL_TEST_STOP], - [AT_CHECK([check_logs "$1"]) - OVS_APP_EXIT_AND_WAIT([ovn-northd]) - OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl], [$OVS_RUNDIR/ovnnb_db.pid]) - OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl], [$OVS_RUNDIR/ovnsb_db.pid])]) +m4_define([OVN_SBCTL_TEST_STOP], [ovn_sbctl_test_stop]) +ovn_sbctl_test_stop() { + AT_CHECK([check_logs "$1"]) + OVS_APP_EXIT_AND_WAIT([ovn-northd]) + OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl], [$OVS_RUNDIR/ovnnb_db.pid]) + OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl], [$OVS_RUNDIR/ovnsb_db.pid]) +} +OVS_END_SHELL_HELPERS + +# OVN_SBCTL_TEST(NAME, TITLE, COMMANDS) +m4_define([OVN_SBCTL_TEST], + [OVS_START_SHELL_HELPERS + $1() { + $3 + } + OVS_END_SHELL_HELPERS + + AT_SETUP([ovn-sbctl - $2 - direct]) + OVN_SBCTL_TEST_START direct + $1 + OVN_SBCTL_TEST_STOP + AT_CLEANUP + + AT_SETUP([ovn-sbctl - $2 - daemon]) + OVN_SBCTL_TEST_START daemon + $1 + OVN_SBCTL_TEST_STOP + AT_CLEANUP]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-sbctl - chassis commands]) -OVN_SBCTL_TEST_START +OVN_SBCTL_TEST([ovn_sbctl_chassis_commands], [ovn-sbctl - chassis commands], [ ovn_init_db ovn-sb AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4]) @@ -61,16 +93,14 @@ AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list encap | 1.2.3.5,vxlan ]) -OVN_SBCTL_TEST_STOP as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -AT_CLEANUP +as +]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-sbctl]) -OVN_SBCTL_TEST_START - +OVN_SBCTL_TEST([ovn_sbctl_commands], [ovn-sbctl], [ AT_CHECK([ovn-nbctl ls-add br-test]) AT_CHECK([ovn-nbctl lsp-add br-test vif0]) AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02]) @@ -131,20 +161,14 @@ mac : [[]] type : vtep options : {vtep_logical_switch=l0, vtep_physical_switch=p0} ]) - -OVN_SBCTL_TEST_STOP -AT_CLEANUP +]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-sbctl - connection]) -OVN_SBCTL_TEST_START - +OVN_SBCTL_TEST([ovn_sbctl_connection], [ovn-sbctl - connection], [ AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock]) AT_CHECK([ovn-sbctl list connection | grep inactivity_probe], [0], [dnl inactivity_probe : 30000 inactivity_probe : 30000 ]) - -OVN_SBCTL_TEST_STOP -AT_CLEANUP +]) \ No newline at end of file diff --git a/utilities/automake.mk b/utilities/automake.mk index 50c0cfded018..a03892f2055a 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -14,7 +14,6 @@ man_MANS += \ utilities/ovn-appctl.8 MAN_ROOTS += \ - utilities/ovn-sbctl.8.in \ utilities/ovn-detrace.1.in # Docker drivers @@ -30,6 +29,7 @@ EXTRA_DIST += \ utilities/ovn-docker-overlay-driver.in \ utilities/ovn-docker-underlay-driver.in \ utilities/ovn-nbctl.8.xml \ + utilities/ovn-sbctl.8.xml \ utilities/ovn-ic-nbctl.8.xml \ utilities/ovn-ic-sbctl.8.xml \ utilities/ovn-appctl.8.xml \ @@ -79,7 +79,10 @@ utilities_ovn_nbctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBD # ovn-sbctl bin_PROGRAMS += utilities/ovn-sbctl -utilities_ovn_sbctl_SOURCES = utilities/ovn-sbctl.c +utilities_ovn_sbctl_SOURCES = \ + utilities/ovn-dbctl.c \ + utilities/ovn-dbctl.h \ + utilities/ovn-sbctl.c utilities_ovn_sbctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la # ovn-ic-nbctl diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c index d815dc5c8c5f..ffe85ce6d5d9 100644 --- a/utilities/ovn-dbctl.c +++ b/utilities/ovn-dbctl.c @@ -327,7 +327,8 @@ enum { }; static char * OVS_WARN_UNUSED_RESULT -handle_main_loop_option(int opt, const char *arg, bool *handled) +handle_main_loop_option(const struct ovn_dbctl_options *dbctl_options, + int opt, const char *arg, bool *handled) { ovs_assert(handled); *handled = true; @@ -338,11 +339,16 @@ handle_main_loop_option(int opt, const char *arg, bool *handled) break; case OPT_NO_WAIT: + if (!dbctl_options->allow_wait) { + return xstrdup("--no-wait not supported"); + } wait_type = NBCTL_WAIT_NONE; break; case OPT_WAIT: - if (!strcmp(arg, "none")) { + if (!dbctl_options->allow_wait) { + return xstrdup("--wait not supported"); + } else if (!strcmp(arg, "none")) { wait_type = NBCTL_WAIT_NONE; } else if (!strcmp(arg, "sb")) { wait_type = NBCTL_WAIT_SB; @@ -355,6 +361,9 @@ handle_main_loop_option(int opt, const char *arg, bool *handled) break; case OPT_PRINT_WAIT_TIME: + if (!dbctl_options->allow_wait) { + return xstrdup("--print-wait-time not supported"); + } print_wait_time = true; break; @@ -486,7 +495,8 @@ apply_options_direct(const struct ovn_dbctl_options *dbctl_options, for (const struct ovs_cmdl_parsed_option *po = parsed_options; po < &parsed_options[n]; po++) { bool handled; - char *error = handle_main_loop_option(po->o->val, po->arg, &handled); + char *error = handle_main_loop_option(dbctl_options, + po->o->val, po->arg, &handled); if (error) { ctl_fatal("%s", error); } @@ -834,7 +844,8 @@ find_option_by_value(const struct option *options, int value) } static char * OVS_WARN_UNUSED_RESULT -server_parse_options(int argc, char *argv[], struct shash *local_options, +server_parse_options(const struct ovn_dbctl_options *dbctl_options, + int argc, char *argv[], struct shash *local_options, int *n_options_p) { static const struct option global_long_options[] = { @@ -865,7 +876,7 @@ server_parse_options(int argc, char *argv[], struct shash *local_options, } bool handled; - error = handle_main_loop_option(c, optarg, &handled); + error = handle_main_loop_option(dbctl_options, c, optarg, &handled); if (error) { goto out; } @@ -967,7 +978,8 @@ server_cmd_run(struct unixctl_conn *conn, int argc, const char **argv_, /* Parse commands & options. */ char *args = process_escape_args(argv); shash_init(&local_options); - error = server_parse_options(argc, argv, &local_options, &n_options); + error = server_parse_options(dbctl_options, + argc, argv, &local_options, &n_options); if (error) { unixctl_command_reply_error(conn, error); goto out; diff --git a/utilities/ovn-dbctl.h b/utilities/ovn-dbctl.h index 5accf3c5e028..a1fbede6b5ce 100644 --- a/utilities/ovn-dbctl.h +++ b/utilities/ovn-dbctl.h @@ -15,7 +15,7 @@ #ifndef OVN_DBCTL_H #define OVN_DBCTL_H 1 -/* ovn-nbctl infrastructure code. */ +/* Common code for ovn-sbctl and ovn-nbctl. */ #include #include "ovsdb-idl.h" @@ -31,6 +31,7 @@ enum nbctl_wait_type { struct ovn_dbctl_options { const char *db_version; /* Database schema version. */ const char *default_db; /* Default database remote. */ + bool allow_wait; /* Allow --wait and related options? */ /* Names of important environment variables. */ const char *options_env_var_name; /* OVN_??_OPTIONS. */ diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index 14840a8fa074..7ae7dcfc4607 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -5986,6 +5986,7 @@ main(int argc, char *argv[]) struct ovn_dbctl_options dbctl_options = { .db_version = nbrec_get_db_version(), .default_db = default_nb_db(), + .allow_wait = true, .options_env_var_name = "OVN_NBCTL_OPTIONS", .daemon_env_var_name = "OVN_NB_DAEMON", diff --git a/utilities/ovn-sbctl.8.in b/utilities/ovn-sbctl.8.in deleted file mode 100644 index 153e72e6c28d..000000000000 --- a/utilities/ovn-sbctl.8.in +++ /dev/null @@ -1,317 +0,0 @@ -.\" -*- nroff -*- -.so lib/ovs.tmac -.TH ovn\-sbctl 8 "@VERSION@" "OVN" "OVN Manual" -.\" This program's name: -.ds PN ovn\-sbctl -. -.SH NAME -ovn\-sbctl \- utility for querying and configuring \fBOVN_Southbound\fR database -. -.SH SYNOPSIS -\fBovn\-sbctl\fR [\fIoptions\fR] \fB\-\-\fR [\fIoptions\fR] \fIcommand -\fR[\fIargs\fR] [\fB\-\-\fR [\fIoptions\fR] \fIcommand \fR[\fIargs\fR]]... -. -.SH DESCRIPTION -The \fBovn\-sbctl\fR program configures the \fBOVN_Southbound\fR database -by providing a high\-level interface to its configuration database. See -\fBovn\-sb\fR(5) for comprehensive documentation of the database schema. -.PP -\fBovn\-sbctl\fR connects to an \fBovsdb\-server\fR process that -maintains an OVN_Southbound configuration database. Using this -connection, it queries and possibly applies changes to the database, -depending on the supplied commands. -.PP -\fBovn\-sbctl\fR can perform any number of commands in a single run, -implemented as a single atomic transaction against the database. -.PP -The \fBovn\-sbctl\fR command line begins with global options (see -\fBOPTIONS\fR below for details). The global options are followed by -one or more commands. Each command should begin with \fB\-\-\fR by -itself as a command-line argument, to separate it from the following -commands. (The \fB\-\-\fR before the first command is optional.) The -command -itself starts with command-specific options, if any, followed by the -command name and any arguments. -. -.SH OPTIONS -. -The following options affect the behavior of \fBovn\-sbctl\fR as a -whole. Some individual commands also accept their own options, which -are given just before the command name. If the first command on the -command line has options, then those options must be separated from -the global options by \fB\-\-\fR. -. -.IP "\fB\-\-db=\fIserver\fR" -The OVSDB database remote to contact. If the \fBOVN_SB_DB\fR -environment variable is set, its value is used as the default. -Otherwise, the default is \fBunix:@RUNDIR@/ovnsb_db.sock\fR, but this -default is unlikely to be useful outside of single-machine OVN test -environments. -.IP -\fIserver\fR may be an OVSDB active or passive connection method, -e.g. \fBssl:192.168.10.5:6640\fR, as described in \fBovsdb\fR(7). -. -.IP "\fB\-\-leader\-only\fR" -.IQ "\fB\-\-no\-leader\-only\fR" -By default, or with \fB\-\-leader\-only\fR, when the database server -is a clustered database, \fBovn\-sbctl\fR will avoid servers other -than the cluster leader. This ensures that any data that -\fBovn\-sbctl\fR reads and reports is up-to-date. With -\fB\-\-no\-leader\-only\fR, \fBovn\-sbctl\fR will use any server in -the cluster, which means that for read-only transactions it can report -and act on stale data (transactions that modify the database are -always serialized even with \fB\-\-no\-leader\-only\fR). Refer to -\fBUnderstanding Cluster Consistency\fR in \fBovsdb\fR(7) for more -information. -. -.IP "\fB\-\-no\-syslog\fR" -By default, \fBovn\-sbctl\fR logs its arguments and the details of any -changes that it makes to the system log. This option disables this -logging. -.IP -This option is equivalent to \fB\-\-verbose=sbctl:syslog:warn\fR. -. -.IP "\fB\-\-oneline\fR" -Modifies the output format so that the output for each command is printed -on a single line. New-line characters that would otherwise separate -lines are printed as \fB\\n\fR, and any instances of \fB\\\fR that -would otherwise appear in the output are doubled. -Prints a blank line for each command that has no output. -This option does not affect the formatting of output from the -\fBlist\fR or \fBfind\fR commands; see \fBTable Formatting Options\fR -below. -. -.IP "\fB\-\-dry\-run\fR" -Prevents \fBovn\-sbctl\fR from actually modifying the database. -. -.IP "\fB\-t \fIsecs\fR" -.IQ "\fB\-\-timeout=\fIsecs\fR" -By default, or with a \fIsecs\fR of \fB0\fR, \fBovn\-sbctl\fR waits -forever for a response from the database. This option limits runtime -to approximately \fIsecs\fR seconds. If the timeout expires, -\fBovn\-sbctl\fR will exit with a \fBSIGALRM\fR signal. (A timeout -would normally happen only if the database cannot be contacted, or if -the system is overloaded.) -. -.IP "\fBOVN_SBCTL_OPTIONS\fR" -User can set one or more options using \fBOVN_SBCTL_OPTIONS\fR environment -variable. Under the Bourne shell this might be done like this: -export \fBOVN_SBCTL_OPTIONS\fR"="--db=unix:sb1.ovsdb --no-leader-only". -However user can still over-ride environment options by passing different -options in cli. When the environment variable is no longer needed, unset it, -e.g.: unset \fBOVN_SBCTL_OPTIONS\fR" -. -.so lib/vlog.man -.so lib/common.man -. -.SS "Table Formatting Options" -These options control the format of output from the \fBlist\fR and -\fBfind\fR commands. -.so lib/table.man -. -.SS "Public Key Infrastructure Options" -.so lib/ssl-bootstrap.man -.so lib/ssl.man -. -.SH COMMANDS -The commands implemented by \fBovn\-sbctl\fR are described in the -sections below. -.SS "OVN_Southbound Commands" -These commands work with an \fBOVN_Southbound\fR database as a whole. -. -.IP "\fBinit\fR" -Initializes the database, if it is empty. If the database has already -been initialized, this command has no effect. -. -.IP "\fBshow\fR" -Prints a brief overview of the database contents. -. -.SS "Chassis Commands" -These commands manipulate \fBOVN_Southbound\fR chassis. -. -.IP "[\fB\-\-may\-exist\fR] \fBchassis\-add \fIchassis\fR \fIencap-type\fR \fIencap-ip\fR" -Creates a new chassis named \fIchassis\fR. \fIencap-type\fR is a -comma-separated list of tunnel types. The chassis will have -one encap entry for each specified tunnel type with \fIencap-ip\fR -as the destination IP for each. -.IP -Without \fB\-\-may\-exist\fR, attempting to create a chassis that -exists is an error. With \fB\-\-may\-exist\fR, this command does -nothing if \fIchassis\fR already exists. -. -.IP "[\fB\-\-if\-exists\fR] \fBchassis\-del \fIchassis\fR" -Deletes \fIchassis\fR and its \fIencaps\fR and \fIgateway_ports\fR. -.IP -Without \fB\-\-if\-exists\fR, attempting to delete a chassis that does -not exist is an error. With \fB\-\-if\-exists\fR, attempting to -delete a chassis that does not exist has no effect. -. -.SS "Port binding Commands" -. -These commands manipulate \fBOVN_Southbound\fR port bindings. -. -.IP "[\fB\-\-may\-exist\fR] \fBlsp\-bind \fIlogical-port\fR \fIchassis\fR" -Binds the logical port named \fIlogical-port\fR to \fIchassis\fR. -.IP -Without \fB\-\-may\-exist\fR, attempting to bind a logical port that -has already been bound is an error. With \fB\-\-may\-exist\fR, this -command does nothing if \fIlogical-port\fR has already been bound to -a chassis. -. -.IP "[\fB\-\-if\-exists\fR] \fBlsp\-unbind\fR \fIlogical-port\fR" -Resets the binding of \fIlogical-port\fR to \fINULL\fR. -.IP -Without \fB\-\-if\-exists\fR, attempting to unbind a logical port -that is not bound is an error. With \fB\-\-if\-exists\fR, attempting -to unbind logical port that is not bound has no effect. -. -.SS "Logical Flow Commands" -. -.IP "[\fB\-\-uuid\fR] [\fB\-\-ovs\fR[\fB=\fIremote\fR]] [\fB\-\-stats\fR] [\fB\-\-vflows\fR] \fBlflow\-list\fR [\fIlogical-datapath\fR] [\fIlflow\fR...]" -List logical flows. If \fIlogical-datapath\fR is specified, only list -flows for that logical datapath. The \fIlogical-datapath\fR may be -given as a UUID or as a datapath name (reporting an error if multiple -datapaths have the same name). -.IP -If at least one \fIlflow\fR is given, only matching logical flows, if -any, are listed. Each \fIlflow\fR may be specified as a UUID or the -first few characters of a UUID, optionally prefixed by \fB0x\fR. -(Because \fBovn\-controller\fR sets OpenFlow flow cookies to the first -32 bits of the corresponding logical flow's UUID, this makes it easy -to look up the logical flow that generated a particular OpenFlow -flow.) -.IP -If \fB\-\-uuid\fR is specified, the output includes the first 32 bits -of each logical flow's UUID. This makes it easier to find the -OpenFlow flows that correspond to a given logical flow. -.IP -If \fB\-\-ovs\fR is included, \fBovn\-sbctl\fR attempts to obtain and -display the OpenFlow flows that correspond to each OVN logical flow. -To do so, \fBovn\-sbctl\fR connects to \fIremote\fR (by default, -\fBunix:@RUNDIR@/br-int.mgmt\fR) over OpenFlow and retrieves the -flows. If \fIremote\fR is specified, it must be an active OpenFlow -connection method described in \fBovsdb\fR(7). Please see the -discussion of the similar \fB\-\-ovs\fR option in \fBovn-trace\fR(8) -for more information about the OpenFlow flow output. -.IP -By default, OpenFlow flow output includes only match and actions. Add -\fB\-\-stats\fR to include all OpenFlow information, such as packet -and byte counters, duration, and timeouts. -.IP -If \fB\-\-vflows\fR is included, other southbound database records directly -used for generating OpenFlow flows are also listed. This includes: -\fIport-bindings\fR, \fImac-bindings\fR, \fImulticast-groups\fR, -\fIchassis\fR. The \fB\-\-ovs\fR and \fB\-\-stats\fR can also be used in -conjunction with \fB\-\-vflows\fR. -. -.IP "[\fB\-\-uuid\fR] \fBdump\-flows\fR [\fIlogical-datapath\fR]" -Alias for \fBlflow\-list\fB. -. -.SS "Remote Connectivity Commands" -. -These commands manipulate the \fBconnections\fR column in the \fBSB_Global\fR -table and rows in the \fBConnection\fR table. When \fBovsdb\-server\fR -is configured to use the \fBconnections\fR column for OVSDB connections, -this allows the administrator to use \fBovn\-sbctl\fR to configure database -connections. -. -.IP "\fBget\-connection\fR" -Prints the configured connection(s). -. -.IP "\fBdel\-connection\fR" -Deletes the configured connection(s). -. -.IP "\fBset\-connection\fR [\fIaccess\-specifier\fR] \fItarget\fR\&..." -Sets the configured manager target or targets. Each \fItarget\fR may -may be an OVSDB active or passive connection method, -e.g. \fBpssl:6640\fR, as described in \fBovsdb\fR(7), -optionally preceded by an optional access-specifier (\fBread\-only\fR or -\fBread\-write\fR). -If provided, the effect of the access specifier persists for subsequent -targets until changed by another access specifier. -. -.SS "SSL Configuration" -When \fBovsdb\-server\fR is configured to connect using SSL, the -following parameters are required: -.TP -\fIprivate-key\fR -Specifies a PEM file containing the private key used for SSL connections. -.TP -\fIcertificate\fR -Specifies a PEM file containing a certificate, signed by the -certificate authority (CA) used by the connection peers, that -certifies the private key, identifying a trustworthy peer. -.TP -\fIca-cert\fR -Specifies a PEM file containing the CA certificate used to verify that -the connection peers are trustworthy. -.PP -These SSL settings apply to all SSL connections made by the southbound -database server. -. -.IP "\fBget\-ssl\fR" -Prints the SSL configuration. -. -.IP "\fBdel\-ssl\fR" -Deletes the current SSL configuration. -. -.IP "[\fB\-\-bootstrap\fR] \fBset\-ssl\fR \fIprivate-key\fR \fIcertificate\fR \fIca-cert\fR [\fIssl-protocol-list\fR [\fIssl-cipher-list\fR]]" -Sets the SSL configuration. The \fB\-\-bootstrap\fR option is described -below. -. -.ST "CA Certificate Bootstrap" -.PP -Ordinarily, all of the files named in the SSL configuration must exist -before SSL connectivity can be used. However, if the \fIca-cert\fR file -does not exist and the \fB\-\-bootstrap\fR -option is given, then \fBovsdb\-server\fR will attempt to obtain the -CA certificate from the target on its first SSL connection and -save it to the named PEM file. If it is successful, it will -immediately drop the connection and reconnect, and from then on all -SSL connections must be authenticated by a certificate signed by the -CA certificate thus obtained. -.PP -\fBThis option exposes the SSL connection to a man-in-the-middle -attack obtaining the initial CA certificate\fR, but it may be useful -for bootstrapping. -.PP -This option is only useful if the SSL peer sends its CA certificate -as part of the SSL certificate chain. The SSL protocol does not -require the controller to send the CA certificate. -. -.SS "Database Commands" -. -These commands query and modify the contents of \fBovsdb\fR tables. -They are a slight abstraction of the \fBovsdb\fR interface and as such -they operate at a lower level than other \fBovs\-sbctl\fR commands. -.PP -.ST "Identifying Tables, Records, and Columns" -.PP -Each of these commands has a \fItable\fR parameter to identify a table -within the database. Many of them also take a \fIrecord\fR parameter -that identifies a particular record within a table. The \fIrecord\fR -parameter may be the UUID for a record, and many tables offer -additional ways to identify records. Some commands also take -\fIcolumn\fR parameters that identify a particular field within the -records in a table. -.PP -For a list of tables and their columns, see \fBovn\-sb\fR(5) or -see the table listing from the \fB--help\fR option. -.PP -Record names must be specified in full and with correct -capitalization, except that UUIDs may be abbreviated to their first 4 -(or more) hex digits, as long as that is unique within the table. -Names of tables and columns are not case-sensitive, and \fB\-\fR and -\fB_\fR are treated interchangeably. Unique abbreviations of table -and column names are acceptable, e.g. \fBaddr\fR or \fBa\fR is -sufficient to identify the \fBAddress_Set\fR table. -. -.so lib/db-ctl-base.man -.SH "EXIT STATUS" -.IP "0" -Successful program execution. -.IP "1" -Usage, syntax, or configuration file error. -.SH "SEE ALSO" -. -.BR ovn\-sb (5). diff --git a/utilities/ovn-sbctl.8.xml b/utilities/ovn-sbctl.8.xml new file mode 100644 index 000000000000..4e6b21c47369 --- /dev/null +++ b/utilities/ovn-sbctl.8.xml @@ -0,0 +1,580 @@ + + +

Name

+

ovn-sbctl -- Open Virtual Network southbound db management utility

+ +

Synopsis

+

ovn-sbctl [options] command [arg...]

+ +

Description

+ +

+ The ovn-sbctl program configures the + OVN_Southbound database by providing a high-level interface + to its configuration database. See ovn-sb(5) for + comprehensive documentation of the database schema. +

+ +

+ ovn-sbctl connects to an ovsdb-server process + that maintains an OVN_Southbound configuration database. Using this + connection, it queries and possibly applies changes to the database, + depending on the supplied commands. +

+ +

+ ovn-sbctl can perform any number of commands in a single + run, implemented as a single atomic transaction against the database. +

+ +

+ The ovn-sbctl command line begins with global options (see + OPTIONS below for details). The global options are followed + by one or more commands. Each command should begin with -- + by itself as a command-line argument, to separate it from the following + commands. (The -- before the first command is optional.) + The command itself starts with command-specific options, if any, followed + by the command name and any arguments. +

+ +

Daemon Mode

+ +

+ When it is invoked in the most ordinary way, ovn-sbctl + connects to an OVSDB server that hosts the southbound database, retrieves + a partial copy of the database that is complete enough to do its work, + sends a transaction request to the server, and receives and processes the + server's reply. In common interactive use, this is fine, but if the + database is large, the step in which ovn-sbctl retrieves a + partial copy of the database can take a long time, which yields poor + performance overall. +

+ +

+ To improve performance in such a case, ovn-sbctl offers a + "daemon mode," in which the user first starts ovn-sbctl + running in the background and afterward uses the daemon to execute + operations. Over several ovn-sbctl command invocations, + this performs better overall because it retrieves a copy of the database + only once at the beginning, not once per program run. +

+ +

+ Use the --detach option to start an ovn-sbctl + daemon. With this option, ovn-sbctl prints the name of a + control socket to stdout. The client should save this name in + environment variable OVN_SB_DAEMON. Under the Bourne shell + this might be done like this: +

+ +
+      export OVN_SB_DAEMON=$(ovn-sbctl --pidfile --detach)
+    
+ +

+ When OVN_SB_DAEMON is set, ovn-sbctl + automatically and transparently uses the daemon to execute its commands. +

+ +

+ When the daemon is no longer needed, kill it and unset the environment + variable, e.g.: +

+ +
+      kill $(cat $OVN_RUNDIR/ovn-sbctl.pid)
+      unset OVN_SB_DAEMON
+    
+ +

+ When using daemon mode, an alternative to the OVN_SB_DAEMON + environment variable is to specify a path for the Unix socket. When + starting the ovn-sbctl daemon, specify the -u option with a + full path to the location of the socket file. Here is an exmple: +

+ +
+      ovn-sbctl --detach -u /tmp/mysock.ctl
+    
+ +

+ Then to connect to the running daemon, use the -u option + with the full path to the socket created when the daemon was started: +

+ +
+      ovn-sbctl -u /tmp/mysock.ctl show
+    
+ +

Daemon Commands

+ +

+ Daemon mode is internally implemented using the same mechanism used by + ovn-appctl. One may also use ovn-appctl + directly with the following commands: +

+ +
+
+ run [options] command + [arg...] [-- [options] + command [arg...] ...] +
+
+ Instructs the daemon process to run one or more ovn-sbctl + commands described above and reply with the results of running these + commands. Accepts the --no-wait, --wait, + --timeout, --dry-run, --oneline, + and the options described under Table Formatting Options + in addition to the the command-specific options. +
+ +
exit
+
Causes ovn-sbctl to gracefully terminate.
+
+ +

Options

+ +

+ The options listed below affect the behavior of ovn-sbctl as + a whole. Some individual commands also accept their own options, which + are given just before the command name. If the first command on the + command line has options, then those options must be separated from the + global options by --. +

+ +

+ ovn-sbctl also accepts options from the + OVN_SBCTL_OPTIONS environment variable, in the same format as + on the command line. Options from the command line override those in the + environment. +

+ +
+
--db database
+
+ The OVSDB database remote to contact. If the OVN_SB_DB + environment variable is set, its value is used as the default. + Otherwise, the default is unix:@RUNDIR@/ovnsb_db.sock, but + this default is unlikely to be useful outside of single-machine OVN + test environments. +
+ +
--leader-only
+
--no-leader-only
+
+ By default, or with --leader-only, when the database + server is a clustered database, ovn-sbctl will avoid + servers other than the cluster leader. This ensures that any data that + ovn-sbctl reads and reports is up-to-date. With + --no-leader-only, ovn-sbctl will use any + server in the cluster, which means that for read-only transactions it + can report and act on stale data (transactions that modify the database + are always serialized even with --no-leader-only). Refer + to Understanding Cluster Consistency in + ovsdb(7) for more information. +
+ +
--shuffle-remotes
+
--no-shuffle-remotes
+
+ By default, or with --shuffle-remotes, when there are + multiple remotes specified in the OVSDB connection string specified by + --db or the OVN_SB_DB environment variable, the + order of the remotes will be shuffled before the client tries to + connect. The remotes will be shuffled only once to a new order before + the first connection attempt. The following retries, if any, will + follow the same new order. The default behavior is to make sure + clients of a clustered database can distribute evenly to all memembers + of the cluster. With --no-shuffle-remotes, + ovn-sbctl will use the original order specified in the + connection string to connect. This allows user to specify the + preferred order, which is particularly useful for testing. +
+ +
--no-syslog
+
+

+ By default, ovn-sbctl logs its arguments and the details + of any changes that it makes to the system log. This option disables + this logging. +

+ +

+ This option is equivalent to + --verbose=sbctl:syslog:warn. +

+
+ +
--oneline
+
+ Modifies the output format so that the output for each command is + printed on a single line. New-line characters that would otherwise + separate lines are printed as \fB\\n\fR, and any instances of \fB\\\fR + that would otherwise appear in the output are doubled. Prints a blank + line for each command that has no output. This option does not affect + the formatting of output from the list or + find commands; see Table Formatting Options + below. +
+ +
--dry-run
+
+ Prevents ovn-sbctl from actually modifying the database. +
+ +
-t secs
+
--timeout=secs
+
+ By default, or with a secs of 0, + ovn-sbctl waits forever for a response from the database. + This option limits runtime to approximately secs seconds. + If the timeout expires, ovn-sbctl will exit with a + SIGALRM signal. (A timeout would normally happen only if + the database cannot be contacted, or if the system is overloaded.) +
+
+ +

Daemon Options

+ + +

Logging options

+ + +

Table Formatting Options

+ These options control the format of output from the list and + find commands. + + +

PKI Options

+

+ PKI configuration is required to use SSL for the connection to the + database. +

+ + + +

Other Options

+ + + +

Commands

+ +

+ The following sections describe the commands that ovn-sbctl + supports. +

+ +

OVN_Southbound Commands

+ +

+ These commands work with an OVN_Southbound database as a + whole. +

+ +
+
init
+
+ Initializes the database, if it is empty. If the database has already + been initialized, this command has no effect. +
+ +
show
+
+ Prints a brief overview of the database contents. +
+
+ +

Chassis Commands

+ +

+ These commands manipulate OVN_Southbound chassis. +

+ +
+
[--may-exist] chassis-add chassis encap-type encap-ip
+ +
+

+ Creates a new chassis named chassis. + encap-type is a comma-separated list of tunnel types. The + chassis will have one encap entry for each specified tunnel type with + encap-ip as the destination IP for each. +

+ +

+ Without \fB\-\-may\-exist\fR, attempting to create a chassis that + exists is an error. With \fB\-\-may\-exist\fR, this command does + nothing if chassis already exists. +

+
+ +
[--if-exists] chassis-del chassis
+
+

+ Deletes chassis and its encaps and + gateway_ports. +

+ +

+ Without --if-exists, attempting to delete a chassis that + does not exist is an error. With --if-exists attempting + to delete a chassis that does not exist has no effect. +

+
+
+ +

Port Binding Commands

+ +

+ These commands manipulate OVN_Southbound port bindings. +

+ +
+
[--may-exist] lsp-bind logical-port chassis
+
+

+ Binds the logical port named logical-port to + chassis. +

+ +

+ Without --may-exist, attempting to bind a logical port + that has already been bound is an error. With + --may-exist, this command does nothing if + logical-port has already been bound to a chassis. +

+
+ +
[--if-exists] lsp-unbind logical-port
+
+

+ Removes the binding of logical-port. +

+ +

+ Without --if-exists, attempting to unbind a logical port + that is not bound is an error. With --if-exists, + attempting to unbind logical port that is not bound has no effect. +

+
+
+ +

Logical Flow Commands

+ +
+
[--uuid] [--ovs[=remote]] [--stats] [--vflows] lflow-list [logical-datapath] [lflow...]
+ +
+

+ List logical flows. If logical-datapath is specified, + only list flows for that logical datapath. The + logical-datapath may be given as a UUID or as a datapath + name (reporting an error if multiple datapaths have the same name). +

+ +

+ If at least one lflow is given, only matching logical + flows, if any, are listed. Each lflow may be specified as + a UUID or the first few characters of a UUID, optionally prefixed by + 0x. (Because ovn-controller sets OpenFlow + flow cookies to the first 32 bits of the corresponding logical flow's + UUID, this makes it easy to look up the logical flow that generated a + particular OpenFlow flow.) +

+ +

+ If --uuid is specified, the output includes the first 32 + bits of each logical flow's UUID. This makes it easier to find the + OpenFlow flows that correspond to a given logical flow. +

+ +

+ If --ovs is included, ovn-sbctl attempts to + obtain and display the OpenFlow flows that correspond to each OVN + logical flow. To do so, ovn-sbctl connects to + remote (by default, + unix:@RUNDIR@/br-int.mgmt) over OpenFlow and retrieves + the flows. If remote is specified, it must be an active + OpenFlow connection method described in ovsdb(7). + Please see the discussion of the similar --ovs option in + ovn-trace(8) for more information about the OpenFlow + flow output. +

+ +

+ By default, OpenFlow flow output includes only match and actions. + Add --stats to include all OpenFlow information, such as + packet and byte counters, duration, and timeouts. +

+ +

+ If --vflows is included, other southbound database + records directly used for generating OpenFlow flows are also + listed. This includes: port-bindings, + mac-bindings, multicast-groups, + chassis. The --ovs and --stats + can also be used in conjunction with --vflows. +

+
+ +
[--uuid] dump-flows [logical-datapath]
+
Alias for lflow-list.
+
+ +

Remote Connectivity Commands

+ +

+ These commands manipulate the connections column in the + SB_Global table and rows in the Connection + table. When ovsdb-server is configured to use the + connections column for OVSDB connections, this allows the + administrator to use \fBovn\-sbctl\fR to configure database connections. +

+ +
+
get-connection
+
+ Prints the configured connection(s). +
+ +
del-connection
+
+ Deletes the configured connection(s). +
+ +
[--inactivity-probe=msecs] set-connection target...
+
+ Sets the configured manager target or targets. Use + --inactivity-probe=msecs to override the + default idle connection inactivity probe time. Use 0 to disable + inactivity probes. +
+
+ +

SSL Configuration Commands

+

+ When ovsdb-server is configured to connect using SSL, the + following parameters are required: +

+ +
+
private-key
+
+ Specifies a PEM file containing the private key used for SSL + connections. +
+ +
certificate
+
+ Specifies a PEM file containing a certificate, signed by the + certificate authority (CA) used by the connection peers, that + certifies the private key, identifying a trustworthy peer. +
+ +
ca-cert
+
+ Specifies a PEM file containing the CA certificate used to verify that + the connection peers are trustworthy. +
+
+ +

+ These SSL settings apply to all SSL connections made by the southbound + database server. +

+ +
+
get-ssl
+
+ Prints the SSL configuration. +
+ +
del-ssl
+
+ Deletes the current SSL configuration. +
+ +
[--bootstrap] set-ssl + private-key certificate ca-cert + [ssl-protocol-list [ssl-cipher-list]]
+
+ Sets the SSL configuration. +
+
+ +

Database Commands

+

+ These commands query and modify the contents of ovsdb + tables. They are a slight abstraction of the ovsdb + interface and as such they operate at a lower level than other + ovn-sbctl commands. +

+ +

Identifying Tables, Records, and Columns

+ +

+ Each of these commands has a table parameter to identify a + table within the database. Many of them also take a record + parameter that identifies a particular record within a table. The + record parameter may be the UUID for a record, which may be + abbreviated to its first 4 (or more) hex digits, as long as that is + unique. Many tables offer additional ways to identify records. Some + commands also take column parameters that identify a + particular field within the records in a table. +

+ +

+ For a list of tables and their columns, see ovn-sb(5) or + see the table listing from the --help option. +

+ +

+ Record names must be specified in full and with correct capitalization, + except that UUIDs may be abbreviated to their first 4 (or more) hex + digits, as long as that is unique within the table. Names of tables and + columns are not case-sensitive, and - and _ are + treated interchangeably. Unique abbreviations of table and column names + are acceptable, e.g. d or dhcp is sufficient + to identify the DHCP_Options table. +

+ + + +

Environment

+ +
+
OVN_SB_DAEMON
+
+ If set, this should name the Unix domain socket for an + ovn-sbctl server process. See Daemon Mode, + above, for more information. +
+ +
OVN_SBCTL_OPTIONS
+
+ If set, a set of options for ovn-sbctl to apply + automatically, in the same form as on the command line. +
+ +
OVN_SB_DB
+
+ If set, the default database to contact when the --db + option is not used. +
+
+ +

Exit Status

+
+
0
+
Successful program execution.
+ +
1
+
Usage, syntax, or network error.
+
+ +

See Also

+ ovn-sb(5), + ovn-appctl(8). + + diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c index e3aa7a68e680..8cccc93f8dfe 100644 --- a/utilities/ovn-sbctl.c +++ b/utilities/ovn-sbctl.c @@ -31,8 +31,10 @@ #include "command-line.h" #include "compiler.h" #include "db-ctl-base.h" +#include "daemon.h" #include "dirs.h" #include "fatal-signal.h" +#include "jsonrpc.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/ofp-actions.h" @@ -43,276 +45,45 @@ #include "openvswitch/vlog.h" #include "lib/ovn-sb-idl.h" #include "lib/ovn-util.h" +#include "memory.h" +#include "ovn-dbctl.h" #include "ovsdb-data.h" #include "ovsdb-idl.h" #include "openvswitch/poll-loop.h" #include "process.h" +#include "simap.h" #include "sset.h" #include "stream-ssl.h" #include "stream.h" #include "table.h" +#include "timer.h" #include "timeval.h" +#include "unixctl.h" #include "util.h" #include "svec.h" VLOG_DEFINE_THIS_MODULE(sbctl); -struct sbctl_context; - -/* --db: The database server to contact. */ -static const char *db; - -/* --oneline: Write each command's output as a single line? */ -static bool oneline; - -/* --dry-run: Do not commit any changes. */ -static bool dry_run; - -/* --timeout: Time to wait for a connection to 'db'. */ -static unsigned int timeout; - -/* Format for table output. */ -static struct table_style table_style = TABLE_STYLE_DEFAULT; - -/* The IDL we're using and the current transaction, if any. - * This is for use by sbctl_exit() only, to allow it to clean up. - * Other code should use its context arguments. */ -static struct ovsdb_idl *the_idl; -static struct ovsdb_idl_txn *the_idl_txn; -OVS_NO_RETURN static void sbctl_exit(int status); - -/* --leader-only, --no-leader-only: Only accept the leader in a cluster. */ -static int leader_only = true; - -static void sbctl_cmd_init(void); -OVS_NO_RETURN static void usage(void); -static void parse_options(int argc, char *argv[], struct shash *local_options); -static void run_prerequisites(struct ctl_command[], size_t n_commands, - struct ovsdb_idl *); -static bool do_sbctl(const char *args, struct ctl_command *, size_t n, - struct ovsdb_idl *); - -int -main(int argc, char *argv[]) +static void +sbctl_add_base_prerequisites(struct ovsdb_idl *idl, + enum nbctl_wait_type wait_type OVS_UNUSED) { - struct ovsdb_idl *idl; - struct ctl_command *commands; - struct shash local_options; - unsigned int seqno; - size_t n_commands; - - ovn_set_program_name(argv[0]); - fatal_ignore_sigpipe(); - vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN); - vlog_set_levels_from_string_assert("reconnect:warn"); - - sbctl_cmd_init(); - - /* Check if options are set via env var. */ - char **argv_ = ovs_cmdl_env_parse_all(&argc, argv, - getenv("OVN_SBCTL_OPTIONS")); - - /* Parse command line. */ - char *args = process_escape_args(argv_); - shash_init(&local_options); - parse_options(argc, argv_, &local_options); - char *error = ctl_parse_commands(argc - optind, argv_ + optind, - &local_options, &commands, &n_commands); - if (error) { - ctl_fatal("%s", error); - } - VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG, - "Called as %s", args); - - ctl_timeout_setup(timeout); - - /* Initialize IDL. */ - idl = the_idl = ovsdb_idl_create(db, &sbrec_idl_class, false, true); - ovsdb_idl_set_leader_only(idl, leader_only); - run_prerequisites(commands, n_commands, idl); - - /* Execute the commands. - * - * 'seqno' is the database sequence number for which we last tried to - * execute our transaction. There's no point in trying to commit more than - * once for any given sequence number, because if the transaction fails - * it's because the database changed and we need to obtain an up-to-date - * view of the database before we try the transaction again. */ - seqno = ovsdb_idl_get_seqno(idl); - for (;;) { - ovsdb_idl_run(idl); - if (!ovsdb_idl_is_alive(idl)) { - int retval = ovsdb_idl_get_last_error(idl); - ctl_fatal("%s: database connection failed (%s)", - db, ovs_retval_to_string(retval)); - } - - if (seqno != ovsdb_idl_get_seqno(idl)) { - seqno = ovsdb_idl_get_seqno(idl); - if (do_sbctl(args, commands, n_commands, idl)) { - break; - } - } - - if (seqno == ovsdb_idl_get_seqno(idl)) { - ovsdb_idl_wait(idl); - poll_block(); - } - } - - for (int i = 0; i < argc; i++) { - free(argv_[i]); - } - free(argv_); - free(args); - exit(EXIT_SUCCESS); + ovsdb_idl_add_table(idl, &sbrec_table_sb_global); } static void -parse_options(int argc, char *argv[], struct shash *local_options) +sbctl_pre_execute(struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn, + enum nbctl_wait_type wait_type OVS_UNUSED) { - enum { - OPT_DB = UCHAR_MAX + 1, - OPT_ONELINE, - OPT_NO_SYSLOG, - OPT_DRY_RUN, - OPT_LOCAL, - OPT_COMMANDS, - OPT_OPTIONS, - OPT_BOOTSTRAP_CA_CERT, - VLOG_OPTION_ENUMS, - TABLE_OPTION_ENUMS, - SSL_OPTION_ENUMS, - }; - static const struct option global_long_options[] = { - {"db", required_argument, NULL, OPT_DB}, - {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, - {"dry-run", no_argument, NULL, OPT_DRY_RUN}, - {"oneline", no_argument, NULL, OPT_ONELINE}, - {"timeout", required_argument, NULL, 't'}, - {"help", no_argument, NULL, 'h'}, - {"commands", no_argument, NULL, OPT_COMMANDS}, - {"options", no_argument, NULL, OPT_OPTIONS}, - {"leader-only", no_argument, &leader_only, true}, - {"no-leader-only", no_argument, &leader_only, false}, - {"version", no_argument, NULL, 'V'}, - VLOG_LONG_OPTIONS, - STREAM_SSL_LONG_OPTIONS, - {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, - TABLE_LONG_OPTIONS, - {NULL, 0, NULL, 0}, - }; - const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1; - char *tmp, *short_options; - - struct option *options; - size_t allocated_options; - size_t n_options; - size_t i; - - tmp = ovs_cmdl_long_options_to_short_options(global_long_options); - short_options = xasprintf("+%s", tmp); - free(tmp); - - /* We want to parse both global and command-specific options here, but - * getopt_long() isn't too convenient for the job. We copy our global - * options into a dynamic array, then append all of the command-specific - * options. */ - options = xmemdup(global_long_options, sizeof global_long_options); - allocated_options = ARRAY_SIZE(global_long_options); - n_options = n_global_long_options; - ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL); - - for (;;) { - int idx; - int c; - - c = getopt_long(argc, argv, short_options, options, &idx); - if (c == -1) { - break; - } - - switch (c) { - case OPT_DB: - db = optarg; - break; - - case OPT_ONELINE: - oneline = true; - break; - - case OPT_NO_SYSLOG: - vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); - break; - - case OPT_DRY_RUN: - dry_run = true; - break; - - case OPT_LOCAL: - if (shash_find(local_options, options[idx].name)) { - ctl_fatal("'%s' option specified multiple times", - options[idx].name); - } - shash_add_nocopy(local_options, - xasprintf("--%s", options[idx].name), - nullable_xstrdup(optarg)); - break; - - case 'h': - usage(); - - case OPT_COMMANDS: - ctl_print_commands(); - /* fall through */ - - case OPT_OPTIONS: - ctl_print_options(global_long_options); - /* fall through */ - - case 'V': - ovn_print_version(0, 0); - printf("DB Schema %s\n", sbrec_get_db_version()); - exit(EXIT_SUCCESS); - - case 't': - if (!str_to_uint(optarg, 10, &timeout) || !timeout) { - ctl_fatal("value %s on -t or --timeout is invalid", optarg); - } - break; - - VLOG_OPTION_HANDLERS - TABLE_OPTION_HANDLERS(&table_style) - STREAM_SSL_OPTION_HANDLERS - - case OPT_BOOTSTRAP_CA_CERT: - stream_ssl_set_ca_cert_file(optarg, true); - break; - - case '?': - exit(EXIT_FAILURE); - - default: - abort(); - - case 0: - break; - } - } - free(short_options); - - if (!db) { - db = default_sb_db(); - } - - for (i = n_global_long_options; options[i].name; i++) { - free(CONST_CAST(char *, options[i].name)); + const struct sbrec_sb_global *sb = sbrec_sb_global_first(idl); + if (!sb) { + /* XXX add verification that table is empty */ + sb = sbrec_sb_global_insert(txn); } - free(options); } static void -usage(void) +sbctl_usage(void) { printf("\ %s: OVN southbound DB management utility\n\ @@ -372,8 +143,12 @@ Other options:\n\ stream_usage("database", true, true, true); exit(EXIT_SUCCESS); } - +/* One should not use ctl_fatal() within commands because it will kill the + * daemon if we're in daemon mode. Use ctl_error() instead and return + * gracefully. */ +#define ctl_fatal dont_use_ctl_fatal_use_ctl_error_and_return + /* ovs-sbctl specific context. Inherits the 'struct ctl_context' as base. */ struct sbctl_context { struct ctl_context base; @@ -420,18 +195,20 @@ sbctl_context_invalidate_cache(struct ctl_context *ctx) shash_destroy_free_data(&sbctl_ctx->port_bindings); } -static void -sbctl_context_populate_cache(struct ctl_context *ctx) +/* Casts 'base' into 'struct sbctl_context' and initializes it if needed. */ +static struct sbctl_context * +sbctl_context_get(struct ctl_context *ctx) { - struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx); + struct sbctl_context *sbctl_ctx + = CONTAINER_OF(ctx, struct sbctl_context, base); + if (sbctl_ctx->cache_valid) { + return sbctl_ctx; + } + const struct sbrec_chassis *chassis_rec; const struct sbrec_port_binding *port_binding_rec; struct sset chassis, port_bindings; - if (sbctl_ctx->cache_valid) { - /* Cache is already populated. */ - return; - } sbctl_ctx->cache_valid = true; shash_init(&sbctl_ctx->chassis); shash_init(&sbctl_ctx->port_bindings); @@ -468,46 +245,48 @@ sbctl_context_populate_cache(struct ctl_context *ctx) bd); } sset_destroy(&port_bindings); + + return sbctl_ctx; +} + +static struct ctl_context * +sbctl_ctx_create(void) +{ + struct sbctl_context *sbctx = xmalloc(sizeof *sbctx); + *sbctx = (struct sbctl_context) { + .cache_valid = false, + }; + return &sbctx->base; } static void -check_conflicts(struct sbctl_context *sbctl_ctx, const char *name, - char *msg) +sbctl_ctx_destroy(struct ctl_context *ctx) { - if (shash_find(&sbctl_ctx->chassis, name)) { - ctl_fatal("%s because a chassis named %s already exists", - msg, name); - } - free(msg); + sbctl_context_invalidate_cache(ctx); + free(ctx); } static struct sbctl_chassis * -find_chassis(struct sbctl_context *sbctl_ctx, const char *name, - bool must_exist) +find_chassis(struct ctl_context *ctx, const char *name, bool must_exist) { - struct sbctl_chassis *sbctl_ch; - - ovs_assert(sbctl_ctx->cache_valid); - - sbctl_ch = shash_find_data(&sbctl_ctx->chassis, name); + struct sbctl_context *sbctl_ctx = sbctl_context_get(ctx); + struct sbctl_chassis *sbctl_ch = shash_find_data(&sbctl_ctx->chassis, + name); if (must_exist && !sbctl_ch) { - ctl_fatal("no chassis named %s", name); + ctl_error(ctx, "no chassis named %s", name); } return sbctl_ch; } static struct sbctl_port_binding * -find_port_binding(struct sbctl_context *sbctl_ctx, const char *name, - bool must_exist) +find_port_binding(struct ctl_context *ctx, const char *name, bool must_exist) { - struct sbctl_port_binding *bd; - - ovs_assert(sbctl_ctx->cache_valid); - - bd = shash_find_data(&sbctl_ctx->port_bindings, name); + struct sbctl_context *sbctl_ctx = sbctl_context_get(ctx); + struct sbctl_port_binding *bd = shash_find_data(&sbctl_ctx->port_bindings, + name); if (must_exist && !bd) { - ctl_fatal("no port named %s", name); + ctl_error(&sbctl_ctx->base, "no port named %s", name); } return bd; @@ -588,7 +367,6 @@ sbctl_init(struct ctl_context *ctx OVS_UNUSED) static void cmd_chassis_add(struct ctl_context *ctx) { - struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx); bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; const char *ch_name, *encap_types, *encap_ip; @@ -596,17 +374,20 @@ cmd_chassis_add(struct ctl_context *ctx) encap_types = ctx->argv[2]; encap_ip = ctx->argv[3]; - sbctl_context_populate_cache(ctx); - if (may_exist) { - struct sbctl_chassis *sbctl_ch; - - sbctl_ch = find_chassis(sbctl_ctx, ch_name, false); - if (sbctl_ch) { + if (find_chassis(ctx, ch_name, false)) { + if (may_exist) { return; } } - check_conflicts(sbctl_ctx, ch_name, - xasprintf("cannot create a chassis named %s", ch_name)); + + struct sbctl_context *sbctl_ctx = sbctl_context_get(ctx); + if (shash_find(&sbctl_ctx->chassis, ch_name)) { + if (!may_exist) { + ctl_error(ctx, "cannot create a chassis named %s because a " + "chassis named %s already exists", ch_name, ch_name); + } + return; + } struct sset encap_set; sset_from_delimited_string(&encap_set, encap_types, ","); @@ -642,8 +423,7 @@ cmd_chassis_del(struct ctl_context *ctx) bool must_exist = !shash_find(&ctx->options, "--if-exists"); struct sbctl_chassis *sbctl_ch; - sbctl_context_populate_cache(ctx); - sbctl_ch = find_chassis(sbctl_ctx, ctx->argv[1], must_exist); + sbctl_ch = find_chassis(ctx, ctx->argv[1], must_exist); if (sbctl_ch) { if (sbctl_ch->ch_cfg) { size_t i; @@ -661,7 +441,6 @@ cmd_chassis_del(struct ctl_context *ctx) static void cmd_lsp_bind(struct ctl_context *ctx) { - struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx); bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; struct sbctl_chassis *sbctl_ch; struct sbctl_port_binding *sbctl_bd; @@ -672,17 +451,21 @@ cmd_lsp_bind(struct ctl_context *ctx) lport_name = ctx->argv[1]; ch_name = ctx->argv[2]; - sbctl_context_populate_cache(ctx); - sbctl_bd = find_port_binding(sbctl_ctx, lport_name, true); - sbctl_ch = find_chassis(sbctl_ctx, ch_name, true); + sbctl_bd = find_port_binding(ctx, lport_name, true); + if (!sbctl_bd) { + return; + } + sbctl_ch = find_chassis(ctx, ch_name, true); + if (!sbctl_ch) { + return; + } if (sbctl_bd->bd_cfg->chassis) { - if (may_exist && sbctl_bd->bd_cfg->chassis == sbctl_ch->ch_cfg) { - return; - } else { - ctl_fatal("lport (%s) has already been binded to chassis (%s)", + if (!may_exist || sbctl_bd->bd_cfg->chassis != sbctl_ch->ch_cfg) { + ctl_error(ctx, "lport (%s) has already been binded to chassis (%s)", lport_name, sbctl_bd->bd_cfg->chassis->name); } + return; } sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg); sbrec_port_binding_set_up(sbctl_bd->bd_cfg, &up, 1); @@ -692,14 +475,12 @@ cmd_lsp_bind(struct ctl_context *ctx) static void cmd_lsp_unbind(struct ctl_context *ctx) { - struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx); bool must_exist = !shash_find(&ctx->options, "--if-exists"); struct sbctl_port_binding *sbctl_bd; char *lport_name; lport_name = ctx->argv[1]; - sbctl_context_populate_cache(ctx); - sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist); + sbctl_bd = find_port_binding(ctx, lport_name, must_exist); if (sbctl_bd) { sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL); sbrec_port_binding_set_up(sbctl_bd->bd_cfg, NULL, 0); @@ -1123,7 +904,9 @@ cmd_lflow_list(struct ctl_context *ctx) char *error = ctl_get_row(ctx, &sbrec_table_datapath_binding, ctx->argv[1], false, &row); if (error) { - ctl_fatal("%s", error); + ctl_error(ctx, "%s", error); + free(error); + return; } datapath = (const struct sbrec_datapath_binding *)row; @@ -1136,8 +919,9 @@ cmd_lflow_list(struct ctl_context *ctx) for (size_t i = 1; i < ctx->argc; i++) { char *s = parse_partial_uuid(ctx->argv[i]); if (!s) { - ctl_fatal("%s is not a UUID or the beginning of a UUID", + ctl_error(ctx, "%s is not a UUID or the beginning of a UUID", ctx->argv[i]); + return; } ctx->argv[i] = s; } @@ -1272,12 +1056,15 @@ sbctl_ip_mcast_flush(struct ctl_context *ctx) char *error = ctl_get_row(ctx, &sbrec_table_datapath_binding, ctx->argv[1], false, &row); if (error) { - ctl_fatal("%s", error); + ctl_error(ctx, "%s", error); + free(error); + return; } dp = (const struct sbrec_datapath_binding *)row; if (!dp) { - ctl_fatal("%s is not a valid datapath", ctx->argv[1]); + ctl_error(ctx, "%s is not a valid datapath", ctx->argv[1]); + return; } sbctl_ip_mcast_flush_switch(ctx, dp); @@ -1564,248 +1351,6 @@ static const struct ctl_table_class tables[SBREC_N_TABLES] = { = {&sbrec_load_balancer_col_name, NULL, NULL}, }; - -static void -sbctl_context_init_command(struct sbctl_context *sbctl_ctx, - struct ctl_command *command) -{ - ctl_context_init_command(&sbctl_ctx->base, command); -} - -static void -sbctl_context_init(struct sbctl_context *sbctl_ctx, - struct ctl_command *command, struct ovsdb_idl *idl, - struct ovsdb_idl_txn *txn, - struct ovsdb_symbol_table *symtab) -{ - ctl_context_init(&sbctl_ctx->base, command, idl, txn, symtab, - sbctl_context_invalidate_cache); - sbctl_ctx->cache_valid = false; -} - -static void -sbctl_context_done_command(struct sbctl_context *sbctl_ctx, - struct ctl_command *command) -{ - ctl_context_done_command(&sbctl_ctx->base, command); -} - -static void -sbctl_context_done(struct sbctl_context *sbctl_ctx, - struct ctl_command *command) -{ - ctl_context_done(&sbctl_ctx->base, command); -} - -static void -run_prerequisites(struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl) -{ - ovsdb_idl_add_table(idl, &sbrec_table_sb_global); - - for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) { - if (c->syntax->prerequisites) { - struct sbctl_context sbctl_ctx; - - ds_init(&c->output); - c->table = NULL; - - sbctl_context_init(&sbctl_ctx, c, idl, NULL, NULL); - (c->syntax->prerequisites)(&sbctl_ctx.base); - if (sbctl_ctx.base.error) { - ctl_fatal("%s", sbctl_ctx.base.error); - } - sbctl_context_done(&sbctl_ctx, c); - - ovs_assert(!c->output.string); - ovs_assert(!c->table); - } - } -} - -static bool -do_sbctl(const char *args, struct ctl_command *commands, size_t n_commands, - struct ovsdb_idl *idl) -{ - struct ovsdb_idl_txn *txn; - enum ovsdb_idl_txn_status status; - struct ovsdb_symbol_table *symtab; - struct sbctl_context sbctl_ctx; - struct ctl_command *c; - struct shash_node *node; - - txn = the_idl_txn = ovsdb_idl_txn_create(idl); - if (dry_run) { - ovsdb_idl_txn_set_dry_run(txn); - } - - ovsdb_idl_txn_add_comment(txn, "ovs-sbctl: %s", args); - - const struct sbrec_sb_global *sb = sbrec_sb_global_first(idl); - if (!sb) { - /* XXX add verification that table is empty */ - sbrec_sb_global_insert(txn); - } - - symtab = ovsdb_symbol_table_create(); - for (c = commands; c < &commands[n_commands]; c++) { - ds_init(&c->output); - c->table = NULL; - } - sbctl_context_init(&sbctl_ctx, NULL, idl, txn, symtab); - for (c = commands; c < &commands[n_commands]; c++) { - sbctl_context_init_command(&sbctl_ctx, c); - if (c->syntax->run) { - (c->syntax->run)(&sbctl_ctx.base); - } - if (sbctl_ctx.base.error) { - ctl_fatal("%s", sbctl_ctx.base.error); - } - sbctl_context_done_command(&sbctl_ctx, c); - - if (sbctl_ctx.base.try_again) { - sbctl_context_done(&sbctl_ctx, NULL); - goto try_again; - } - } - sbctl_context_done(&sbctl_ctx, NULL); - - SHASH_FOR_EACH (node, &symtab->sh) { - struct ovsdb_symbol *symbol = node->data; - if (!symbol->created) { - ctl_fatal("row id \"%s\" is referenced but never created (e.g. " - "with \"-- --id=%s create ...\")", - node->name, node->name); - } - if (!symbol->strong_ref) { - if (!symbol->weak_ref) { - VLOG_WARN("row id \"%s\" was created but no reference to it " - "was inserted, so it will not actually appear in " - "the database", node->name); - } else { - VLOG_WARN("row id \"%s\" was created but only a weak " - "reference to it was inserted, so it will not " - "actually appear in the database", node->name); - } - } - } - - status = ovsdb_idl_txn_commit_block(txn); - if (status == TXN_UNCHANGED || status == TXN_SUCCESS) { - for (c = commands; c < &commands[n_commands]; c++) { - if (c->syntax->postprocess) { - sbctl_context_init(&sbctl_ctx, c, idl, txn, symtab); - (c->syntax->postprocess)(&sbctl_ctx.base); - if (sbctl_ctx.base.error) { - ctl_fatal("%s", sbctl_ctx.base.error); - } - sbctl_context_done(&sbctl_ctx, c); - } - } - } - - switch (status) { - case TXN_UNCOMMITTED: - case TXN_INCOMPLETE: - OVS_NOT_REACHED(); - - case TXN_ABORTED: - /* Should not happen--we never call ovsdb_idl_txn_abort(). */ - ctl_fatal("transaction aborted"); - - case TXN_UNCHANGED: - case TXN_SUCCESS: - break; - - case TXN_TRY_AGAIN: - goto try_again; - - case TXN_ERROR: - ctl_fatal("transaction error: %s", ovsdb_idl_txn_get_error(txn)); - - case TXN_NOT_LOCKED: - /* Should not happen--we never call ovsdb_idl_set_lock(). */ - ctl_fatal("database not locked"); - - default: - OVS_NOT_REACHED(); - } - - ovsdb_symbol_table_destroy(symtab); - - for (c = commands; c < &commands[n_commands]; c++) { - struct ds *ds = &c->output; - - if (c->table) { - table_print(c->table, &table_style); - } else if (oneline) { - size_t j; - - ds_chomp(ds, '\n'); - for (j = 0; j < ds->length; j++) { - int ch = ds->string[j]; - switch (ch) { - case '\n': - fputs("\\n", stdout); - break; - - case '\\': - fputs("\\\\", stdout); - break; - - default: - putchar(ch); - } - } - putchar('\n'); - } else { - fputs(ds_cstr(ds), stdout); - } - ds_destroy(&c->output); - table_destroy(c->table); - free(c->table); - - shash_destroy_free_data(&c->options); - } - free(commands); - ovsdb_idl_txn_destroy(txn); - ovsdb_idl_destroy(idl); - - return true; - -try_again: - /* Our transaction needs to be rerun, or a prerequisite was not met. Free - * resources and return so that the caller can try again. */ - ovsdb_idl_txn_abort(txn); - ovsdb_idl_txn_destroy(txn); - the_idl_txn = NULL; - - ovsdb_symbol_table_destroy(symtab); - for (c = commands; c < &commands[n_commands]; c++) { - ds_destroy(&c->output); - table_destroy(c->table); - free(c->table); - } - return false; -} - -/* Frees the current transaction and the underlying IDL and then calls - * exit(status). - * - * Freeing the transaction and the IDL is not strictly necessary, but it makes - * for a clean memory leak report from valgrind in the normal case. That makes - * it easier to notice real memory leaks. */ -static void -sbctl_exit(int status) -{ - if (the_idl_txn) { - ovsdb_idl_txn_abort(the_idl_txn); - ovsdb_idl_txn_destroy(the_idl_txn); - } - ovsdb_idl_destroy(the_idl); - exit(status); -} - static const struct ctl_command_syntax sbctl_commands[] = { { "init", 0, 0, "", NULL, sbctl_init, NULL, "", RW }, @@ -1850,11 +1395,31 @@ static const struct ctl_command_syntax sbctl_commands[] = { {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO}, }; -/* Registers sbctl and common db commands. */ -static void -sbctl_cmd_init(void) +int +main(int argc, char *argv[]) { - ctl_init(&sbrec_idl_class, sbrec_table_classes, tables, - cmd_show_tables, sbctl_exit); - ctl_register_commands(sbctl_commands); + struct ovn_dbctl_options dbctl_options = { + .db_version = sbrec_get_db_version(), + .default_db = default_sb_db(), + .allow_wait = false, + + .options_env_var_name = "OVN_SBCTL_OPTIONS", + .daemon_env_var_name = "OVN_SB_DAEMON", + + .idl_class = &sbrec_idl_class, + .tables = tables, + .cmd_show_table = cmd_show_tables, + .commands = sbctl_commands, + + .usage = sbctl_usage, + .add_base_prerequisites = sbctl_add_base_prerequisites, + .pre_execute = sbctl_pre_execute, + .post_execute = NULL, + + .ctx_create = sbctl_ctx_create, + .ctx_destroy = sbctl_ctx_destroy, + }; + + return ovn_dbctl_main(argc, argv, &dbctl_options); } + From patchwork Fri May 7 04:06:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475320 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxk76KvNz9sPf for ; Fri, 7 May 2021 14:07:43 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 62AB383D42; Fri, 7 May 2021 04:07:41 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uKbHy1UvxX9Y; Fri, 7 May 2021 04:07:34 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTP id E30F983DEF; Fri, 7 May 2021 04:07:32 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 99A65C0001; Fri, 7 May 2021 04:07:32 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3DC16C0001 for ; Fri, 7 May 2021 04:07:31 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 8F8CC40377 for ; Fri, 7 May 2021 04:07:25 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id a4a9n5kMZkeN for ; Fri, 7 May 2021 04:07:23 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 774FA402F5 for ; Fri, 7 May 2021 04:07:22 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id DC085C0007; Fri, 7 May 2021 04:07:19 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:41 -0700 Message-Id: <20210507040659.26830-10-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 09/27] ovn-nbctl: Don't replicate entire database unnecessarily. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" ovn-nbctl was retrieving a replica of the entire northbound database regardless of what it was asked to do. This was unnecessary, but it was not written to be smart enough to just retrieve what it needed. This commit fixes the problem. It makes "ovn-nbctl init", for example, run instantly on a big database, whereas before it could take arbitrarily long. Signed-off-by: Ben Pfaff --- utilities/ovn-dbctl.c | 2 +- utilities/ovn-nbctl.c | 1028 +++++++++++++++++++++++++++++++++++------ 2 files changed, 900 insertions(+), 130 deletions(-) diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c index ffe85ce6d5d9..12cbb8cacb03 100644 --- a/utilities/ovn-dbctl.c +++ b/utilities/ovn-dbctl.c @@ -180,7 +180,7 @@ ovn_dbctl_main(int argc, char *argv[], } /* Initialize IDL. */ idl = the_idl = ovsdb_idl_create_unconnected(dbctl_options->idl_class, - true); + daemon_mode); ovsdb_idl_set_shuffle_remotes(idl, shuffle_remotes); /* "retry" is true iff in daemon mode. */ ovsdb_idl_set_remote(idl, db, daemon_mode); diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index 7ae7dcfc4607..ed3b206d06fa 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -60,12 +60,13 @@ nbctl_add_base_prerequisites(struct ovsdb_idl *idl, force_wait = false; ovsdb_idl_add_table(idl, &nbrec_table_nb_global); - if (wait_type == NBCTL_WAIT_SB) { + if (wait_type != NBCTL_WAIT_NONE) { ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg); ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg_timestamp); - } else if (wait_type == NBCTL_WAIT_HV) { - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg); - ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg_timestamp); + if (wait_type == NBCTL_WAIT_HV) { + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg); + ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg_timestamp); + } } } @@ -190,6 +191,20 @@ nbctl_ctx_destroy(struct ctl_context *base) free(nbctx); } +static void +nbctl_pre_context(struct ctl_context *base) +{ + ovsdb_idl_add_column(base->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(base->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(base->idl, &nbrec_logical_switch_port_col_name); + + ovsdb_idl_add_column(base->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(base->idl, &nbrec_logical_router_col_ports); + + ovsdb_idl_add_column(base->idl, &nbrec_logical_router_port_col_name); +} + /* Casts 'base' into 'struct nbctl_context' and initializes it if needed. */ static struct nbctl_context * nbctl_context_get(struct ctl_context *base) @@ -797,6 +812,39 @@ nbctl_sync(struct ctl_context *ctx OVS_UNUSED) { } +static void +nbctl_pre_show(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_external_ids); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_external_ids); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_type); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_parent_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_tag); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_addresses); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_options); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_external_ids); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_ports); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_nat); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_mac); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_networks); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_gateway_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_chassis_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_port_range); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_type); +} + static void nbctl_show(struct ctl_context *ctx) { @@ -834,6 +882,12 @@ nbctl_show(struct ctl_context *ctx) } } +static void +nbctl_pre_ls_add(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); +} + static void nbctl_ls_add(struct ctl_context *ctx) { @@ -876,6 +930,12 @@ nbctl_ls_add(struct ctl_context *ctx) } } +static void +nbctl_pre_ls_del(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); +} + static void nbctl_ls_del(struct ctl_context *ctx) { @@ -901,6 +961,12 @@ nbctl_ls_del(struct ctl_context *ctx) nbrec_logical_switch_delete(ls); } +static void +nbctl_pre_ls_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); +} + static void nbctl_ls_list(struct ctl_context *ctx) { @@ -983,6 +1049,19 @@ ls_get_name(const struct nbrec_logical_switch *ls, return uuid_s; } +static void +nbctl_pre_lsp_add(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_parent_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_tag_request); +} + static void nbctl_lsp_add(struct ctl_context *ctx) { @@ -1089,6 +1168,17 @@ nbctl_lsp_add(struct ctl_context *ctx) shash_add(&nbctx->lsp_to_ls_map, lsp_name, ls); } +static void +nbctl_pre_lsp_del(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); +} + /* Removes logical switch port 'lsp' from the logical switch 'ls'. */ static void remove_lsp(struct ctl_context *ctx, @@ -1138,6 +1228,15 @@ nbctl_lsp_del(struct ctl_context *ctx) remove_lsp(ctx, ls, lsp); } +static void +nbctl_pre_lsp_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); +} + static void nbctl_lsp_list(struct ctl_context *ctx) { @@ -1167,6 +1266,13 @@ nbctl_lsp_list(struct ctl_context *ctx) free(nodes); } +static void +nbctl_pre_lsp_get_parent(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_parent_name); +} + static void nbctl_lsp_get_parent(struct ctl_context *ctx) { @@ -1182,6 +1288,13 @@ nbctl_lsp_get_parent(struct ctl_context *ctx) } } +static void +nbctl_pre_lsp_get_tag(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_tag); +} + static void nbctl_lsp_get_tag(struct ctl_context *ctx) { @@ -1197,6 +1310,19 @@ nbctl_lsp_get_tag(struct ctl_context *ctx) } } +static void +nbctl_pre_lsp_set_addresses(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_addresses); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_port_col_dynamic_addresses); +} + static char * lsp_contains_duplicate_ip(struct lport_addresses *laddrs1, struct lport_addresses *laddrs2, @@ -1322,6 +1448,13 @@ nbctl_lsp_set_addresses(struct ctl_context *ctx) (const char **) ctx->argv + 2, ctx->argc - 2); } +static void +nbctl_pre_lsp_get_addresses(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_addresses); +} + static void nbctl_lsp_get_addresses(struct ctl_context *ctx) { @@ -1348,6 +1481,14 @@ nbctl_lsp_get_addresses(struct ctl_context *ctx) svec_destroy(&addresses); } +static void +nbctl_pre_lsp_port_security(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_port_col_port_security); +} + static void nbctl_lsp_set_port_security(struct ctl_context *ctx) { @@ -1388,6 +1529,13 @@ nbctl_lsp_get_port_security(struct ctl_context *ctx) svec_destroy(&addrs); } +static void +nbctl_pre_lsp_get_up(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_up); +} + static void nbctl_lsp_get_up(struct ctl_context *ctx) { @@ -1403,6 +1551,13 @@ nbctl_lsp_get_up(struct ctl_context *ctx) "%s\n", (lsp->up && *lsp->up) ? "up" : "down"); } +static void +nbctl_pre_lsp_enabled(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_enabled); +} + static char * OVS_WARN_UNUSED_RESULT parse_enabled(const char *state, bool *enabled_p) { @@ -1455,6 +1610,13 @@ nbctl_lsp_get_enabled(struct ctl_context *ctx) !lsp->enabled || *lsp->enabled ? "enabled" : "disabled"); } +static void +nbctl_pre_lsp_type(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_type); +} + static void nbctl_lsp_set_type(struct ctl_context *ctx) { @@ -1490,6 +1652,13 @@ nbctl_lsp_get_type(struct ctl_context *ctx) ds_put_format(&ctx->output, "%s\n", lsp->type); } +static void +nbctl_pre_lsp_options(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_options); +} + static void nbctl_lsp_set_options(struct ctl_context *ctx) { @@ -1535,6 +1704,16 @@ nbctl_lsp_get_options(struct ctl_context *ctx) } } +static void +nbctl_pre_lsp_dhcpv4_options(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_port_col_dhcpv4_options); + + ovsdb_idl_add_column(ctx->idl, &nbrec_dhcp_options_col_cidr); +} + static void nbctl_lsp_set_dhcpv4_options(struct ctl_context *ctx) { @@ -1569,6 +1748,16 @@ nbctl_lsp_set_dhcpv4_options(struct ctl_context *ctx) nbrec_logical_switch_port_set_dhcpv4_options(lsp, dhcp_opt); } +static void +nbctl_pre_lsp_dhcpv6_options(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_port_col_dhcpv6_options); + + ovsdb_idl_add_column(ctx->idl, &nbrec_dhcp_options_col_cidr); +} + static void nbctl_lsp_set_dhcpv6_options(struct ctl_context *ctx) { @@ -1639,6 +1828,15 @@ nbctl_lsp_get_dhcpv6_options(struct ctl_context *ctx) } } +static void +nbctl_pre_lsp_get_ls(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); +} + static void nbctl_lsp_get_ls(struct ctl_context *ctx) { @@ -1846,6 +2044,32 @@ parse_priority(const char *arg, int64_t *priority_p) return NULL; } +static void +nbctl_pre_acl(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_acls); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_acls); + + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_direction); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_match); +} + +static void +nbctl_pre_acl_list(struct ctl_context *ctx) +{ + nbctl_pre_acl(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_action); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_log); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_severity); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_meter); +} + static void nbctl_acl_add(struct ctl_context *ctx) { @@ -2009,6 +2233,19 @@ nbctl_acl_del(struct ctl_context *ctx) } } +static void +nbctl_pre_qos_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_qos_rules); + + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_direction); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_match); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_bandwidth); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_action); +} + static void nbctl_qos_list(struct ctl_context *ctx) { @@ -2058,6 +2295,17 @@ nbctl_qos_list(struct ctl_context *ctx) free(qos_rules); } +static void +nbctl_pre_qos_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_qos_rules); + + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_direction); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_match); +} + static void nbctl_qos_add(struct ctl_context *ctx) { @@ -2159,6 +2407,17 @@ nbctl_qos_add(struct ctl_context *ctx) nbrec_logical_switch_update_qos_rules_addvalue(ls, qos); } +static void +nbctl_pre_qos_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_qos_rules); + + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_direction); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_match); +} + static void nbctl_qos_del(struct ctl_context *ctx) { @@ -2261,6 +2520,19 @@ meter_cmp(const void *meter1_, const void *meter2_) return strcmp(meter1->name, meter2->name); } +static void +nbctl_pre_meter_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_fair); + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_bands); + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_unit); + + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_band_col_action); + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_band_col_rate); + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_band_col_burst_size); +} + static void nbctl_meter_list(struct ctl_context *ctx) { @@ -2309,6 +2581,12 @@ nbctl_meter_list(struct ctl_context *ctx) free(meters); } +static void +nbctl_pre_meter_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_name); +} + static void nbctl_meter_add(struct ctl_context *ctx) { @@ -2374,6 +2652,12 @@ nbctl_meter_add(struct ctl_context *ctx) } } +static void +nbctl_pre_meter_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_meter_col_name); +} + static void nbctl_meter_del(struct ctl_context *ctx) { @@ -2398,6 +2682,14 @@ nbctl_meter_del(struct ctl_context *ctx) } } +static void +nbctl_pre_lb_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_protocol); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_vips); +} + static void nbctl_lb_add(struct ctl_context *ctx) { @@ -2542,6 +2834,13 @@ out: ds_destroy(&lb_vip_normalized_ds); } +static void +nbctl_pre_lb_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_vips); +} + static void nbctl_lb_del(struct ctl_context *ctx) { @@ -2582,6 +2881,14 @@ nbctl_lb_del(struct ctl_context *ctx) nbrec_load_balancer_delete(lb); } +static void +nbctl_pre_lb_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_protocol); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_vips); +} + static void lb_info_add_smap(const struct nbrec_load_balancer *lb, struct smap *lbs, int vip_width) @@ -2684,6 +2991,15 @@ nbctl_lb_list(struct ctl_context *ctx) } } +static void +nbctl_pre_lr_lb_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); +} + static void nbctl_lr_lb_add(struct ctl_context *ctx) { @@ -2720,6 +3036,15 @@ nbctl_lr_lb_add(struct ctl_context *ctx) nbrec_logical_router_update_load_balancer_addvalue(lr, new_lb); } +static void +nbctl_pre_lr_lb_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); +} + static void nbctl_lr_lb_del(struct ctl_context *ctx) { @@ -2763,6 +3088,17 @@ nbctl_lr_lb_del(struct ctl_context *ctx) } } +static void +nbctl_pre_lr_lb_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_protocol); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_vips); +} + static void nbctl_lr_lb_list(struct ctl_context *ctx) { @@ -2791,6 +3127,15 @@ nbctl_lr_lb_list(struct ctl_context *ctx) smap_destroy(&lbs); } +static void +nbctl_pre_ls_lb_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); +} + static void nbctl_ls_lb_add(struct ctl_context *ctx) { @@ -2827,6 +3172,15 @@ nbctl_ls_lb_add(struct ctl_context *ctx) nbrec_logical_switch_update_load_balancer_addvalue(ls, new_lb); } +static void +nbctl_pre_ls_lb_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); +} + static void nbctl_ls_lb_del(struct ctl_context *ctx) { @@ -2870,6 +3224,17 @@ nbctl_ls_lb_del(struct ctl_context *ctx) } } +static void +nbctl_pre_ls_lb_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_load_balancer); + + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_protocol); + ovsdb_idl_add_column(ctx->idl, &nbrec_load_balancer_col_vips); +} + static void nbctl_ls_lb_list(struct ctl_context *ctx) { @@ -2898,6 +3263,12 @@ nbctl_ls_lb_list(struct ctl_context *ctx) smap_destroy(&lbs); } +static void +nbctl_pre_lr_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); +} + static void nbctl_lr_add(struct ctl_context *ctx) { @@ -2940,6 +3311,14 @@ nbctl_lr_add(struct ctl_context *ctx) } } +static void +nbctl_pre_lr_del(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); +} + static void nbctl_lr_del(struct ctl_context *ctx) { @@ -2965,6 +3344,12 @@ nbctl_lr_del(struct ctl_context *ctx) nbrec_logical_router_delete(lr); } +static void +nbctl_pre_lr_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); +} + static void nbctl_lr_list(struct ctl_context *ctx) { @@ -3040,6 +3425,12 @@ nbctl_dhcp_options_create(struct ctl_context *ctx) smap_destroy(&ext_ids); } +static void +nbctl_pre_dhcp_options_options(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_dhcp_options_col_options); +} + static void nbctl_dhcp_options_set_options(struct ctl_context *ctx) { @@ -3081,6 +3472,12 @@ nbctl_dhcp_options_get_options(struct ctl_context *ctx) } } +static void +nbctl_pre_dhcp_options_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_table(ctx->idl, &nbrec_table_dhcp_options); +} + static void nbctl_dhcp_options_del(struct ctl_context *ctx) { @@ -3100,6 +3497,12 @@ nbctl_dhcp_options_del(struct ctl_context *ctx) nbrec_dhcp_options_delete(dhcp_opts); } +static void +nbctl_pre_dhcp_options_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_dhcp_options_col_cidr); +} + static void nbctl_dhcp_options_list(struct ctl_context *ctx) { @@ -3201,6 +3604,16 @@ normalize_addr_str(const char *orig_addr) return ret; } +static void +nbctl_pre_lr_policy_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_policies); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_match); +} + static void nbctl_lr_policy_add(struct ctl_context *ctx) { @@ -3341,6 +3754,16 @@ nbctl_lr_policy_add(struct ctl_context *ctx) free(nexthops); } +static void +nbctl_pre_lr_policy_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_policies); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_match); +} + static void nbctl_lr_policy_del(struct ctl_context *ctx) { @@ -3462,6 +3885,19 @@ print_routing_policy(const struct nbrec_logical_router_policy *policy, ds_put_char(s, '\n'); } +static void +nbctl_pre_lr_policy_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_policies); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_priority); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_match); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_nexthop); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_action); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_options); +} + static void nbctl_lr_policy_list(struct ctl_context *ctx) { @@ -3531,8 +3967,29 @@ nbctl_lr_get_route(const struct nbrec_logical_router *lr, char *prefix, } return NULL; } - +static void +nbctl_pre_lr_route_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_static_routes); + + ovsdb_idl_add_column(ctx->idl, &nbrec_bfd_col_dst_ip); + + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_ip_prefix); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_nexthop); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_output_port); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_policy); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_bfd); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_options); +} + static void nbctl_lr_route_add(struct ctl_context *ctx) { @@ -3682,6 +4139,23 @@ cleanup: free(prefix); } +static void +nbctl_pre_lr_route_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_static_routes); + + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_policy); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_ip_prefix); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_nexthop); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_output_port); + +} + static void nbctl_lr_route_del(struct ctl_context *ctx) { @@ -3859,6 +4333,22 @@ done: return ret; } +static void +nbctl_pre_lr_nat_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_nat); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_type); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_port); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_mac); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_options); +} + static void nbctl_lr_nat_add(struct ctl_context *ctx) { @@ -4077,6 +4567,17 @@ cleanup: free(new_external_ip); } +static void +nbctl_pre_lr_nat_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_nat); + + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_type); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_ip); +} + static void nbctl_lr_nat_del(struct ctl_context *ctx) { @@ -4150,6 +4651,20 @@ cleanup: free(nat_ip); } +static void +nbctl_pre_lr_nat_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_nat); + + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_type); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_port_range); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_mac); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_port); +} + static void nbctl_lr_nat_list(struct ctl_context *ctx) { @@ -4193,6 +4708,21 @@ nbctl_lr_nat_list(struct ctl_context *ctx) smap_destroy(&lr_nats); } +static void +nbctl_pre_lr_nat_set_ext_ips(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_nat); + + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_logical_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_external_ip); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_type); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_exempted_ext_ips); + ovsdb_idl_add_column(ctx->idl, &nbrec_nat_col_allowed_ext_ips); + + ovsdb_idl_add_column(ctx->idl, &nbrec_address_set_col_name); +} + static void nbctl_lr_nat_set_ext_ips(struct ctl_context *ctx) { @@ -4362,6 +4892,17 @@ gc_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist, return NULL; } +static void +nbctl_pre_lrp_set_gateway_chassis(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_port_col_gateway_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_priority); +} + static void nbctl_lrp_set_gateway_chassis(struct ctl_context *ctx) { @@ -4414,6 +4955,16 @@ nbctl_lrp_set_gateway_chassis(struct ctl_context *ctx) free(gc_name); } +static void +nbctl_pre_lrp_del_gateway_chassis(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_port_col_gateway_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_chassis_name); +} + /* Removes logical router port 'lrp->gateway_chassis[idx]'. */ static void remove_gc(const struct nbrec_logical_router_port *lrp, size_t idx) @@ -4465,6 +5016,17 @@ nbctl_lrp_del_gateway_chassis(struct ctl_context *ctx) chassis_name, ctx->argv[1]); } +static void +nbctl_pre_lrp_get_gateway_chassis(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_port_col_gateway_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_priority); +} + /* Print a list of gateway chassis. */ static void nbctl_lrp_get_gateway_chassis(struct ctl_context *ctx) @@ -4507,6 +5069,20 @@ lrp_network_sset(const char **networks, int n_networks) return network_set; } +static void +nbctl_pre_lrp_add(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_networks); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_mac); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_peer); +} + static void nbctl_lrp_add(struct ctl_context *ctx) { @@ -4688,6 +5264,16 @@ remove_lrp(struct ctl_context *ctx, nbrec_logical_router_port_delete(lrp); } +static void +nbctl_pre_lrp_del(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_ports); +} + static void nbctl_lrp_del(struct ctl_context *ctx) { @@ -4714,6 +5300,15 @@ nbctl_lrp_del(struct ctl_context *ctx) remove_lrp(ctx, lr, lrp); } +static void +nbctl_pre_lrp_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_ports); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); +} + /* Print a list of logical router ports. */ static void nbctl_lrp_list(struct ctl_context *ctx) @@ -4744,6 +5339,13 @@ nbctl_lrp_list(struct ctl_context *ctx) free(nodes); } +static void +nbctl_pre_lrp_enabled(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_enabled); +} + /* Set the logical router port admin-enabled state. */ static void nbctl_lrp_set_enabled(struct ctl_context *ctx) @@ -4791,6 +5393,13 @@ nbctl_lrp_get_enabled(struct ctl_context *ctx) *lrp->enabled ? "enabled" : "disabled"); } +static void +nbctl_pre_lrp_redirect_type(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_options); +} + /* Set the logical router port redirect type. */ static void nbctl_lrp_set_redirect_type(struct ctl_context *ctx) @@ -4898,6 +5507,20 @@ fwd_group_to_logical_switch(struct ctl_context *ctx, return ls; } +static void +nbctl_pre_fwd_group_add(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_col_forwarding_groups); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); +} + static void nbctl_fwd_group_add(struct ctl_context *ctx) { @@ -4986,6 +5609,21 @@ nbctl_fwd_group_add(struct ctl_context *ctx) nbrec_logical_switch_update_forwarding_groups_addvalue(ls, fwd_group); } +static void +nbctl_pre_fwd_group_del(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_child_port); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_switch_col_forwarding_groups); +} + static void nbctl_fwd_group_del(struct ctl_context *ctx) { @@ -5013,6 +5651,21 @@ nbctl_fwd_group_del(struct ctl_context *ctx) } } +static void +nbctl_pre_fwd_group_list(struct ctl_context *ctx) +{ + nbctl_pre_context(ctx); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_child_port); + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_vip); + ovsdb_idl_add_column(ctx->idl, &nbrec_forwarding_group_col_vmac); +} + static void fwd_group_list_all(struct ctl_context *ctx, const char *ls_name) { @@ -5187,6 +5840,28 @@ print_route(const struct nbrec_logical_router_static_route *route, ds_put_char(s, '\n'); } +static void +nbctl_pre_lr_route_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_static_routes); + + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_policy); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_ip_prefix); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_nexthop); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_output_port); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_external_ids); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_options); + ovsdb_idl_add_column(ctx->idl, + &nbrec_logical_router_static_route_col_bfd); +} + static void nbctl_lr_route_list(struct ctl_context *ctx) { @@ -5501,6 +6176,12 @@ out: return error; } +static void +cmd_pre_pg_add(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); +} + static void cmd_pg_add(struct ctl_context *ctx) { @@ -5513,6 +6194,15 @@ cmd_pg_add(struct ctl_context *ctx) } } +static void +cmd_pre_pg_set_ports(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name); + + ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_ports); +} + static void cmd_pg_set_ports(struct ctl_context *ctx) { @@ -5528,6 +6218,12 @@ cmd_pg_set_ports(struct ctl_context *ctx) ctx->error = set_ports_on_pg(ctx, pg, ctx->argv + 2, ctx->argc - 2); } +static void +cmd_pre_pg_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_name); +} + static void cmd_pg_del(struct ctl_context *ctx) { @@ -5582,6 +6278,12 @@ cmd_ha_ch_grp_add(struct ctl_context *ctx) nbrec_ha_chassis_group_set_name(ha_ch_grp, name); } +static void +pre_ha_ch_grp_del(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_name); +} + static void cmd_ha_ch_grp_del(struct ctl_context *ctx) { @@ -5595,6 +6297,16 @@ cmd_ha_ch_grp_del(struct ctl_context *ctx) } } +static void +pre_ha_ch_grp_list(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_ha_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_chassis_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_priority); +} + static void cmd_ha_ch_grp_list(struct ctl_context *ctx) { @@ -5616,6 +6328,16 @@ cmd_ha_ch_grp_list(struct ctl_context *ctx) } } +static void +pre_ha_ch_grp_add_chassis(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_ha_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_chassis_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_priority); +} + static void cmd_ha_ch_grp_add_chassis(struct ctl_context *ctx) { @@ -5654,6 +6376,15 @@ cmd_ha_ch_grp_add_chassis(struct ctl_context *ctx) nbrec_ha_chassis_group_update_ha_chassis_addvalue(ha_ch_grp, ha_chassis); } +static void +pre_ha_ch_grp_remove_chassis(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_ha_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_chassis_name); +} + static void cmd_ha_ch_grp_remove_chassis(struct ctl_context *ctx) { @@ -5683,6 +6414,16 @@ cmd_ha_ch_grp_remove_chassis(struct ctl_context *ctx) nbrec_ha_chassis_delete(ha_chassis); } +static void +pre_ha_ch_grp_set_chassis_prio(struct ctl_context *ctx) +{ + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_group_col_ha_chassis); + + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_chassis_name); + ovsdb_idl_add_column(ctx->idl, &nbrec_ha_chassis_col_priority); +} + static void cmd_ha_ch_grp_set_chassis_prio(struct ctl_context *ctx) { @@ -5782,168 +6523,195 @@ static const struct ctl_table_class tables[NBREC_N_TABLES] = { static const struct ctl_command_syntax nbctl_commands[] = { { "init", 0, 0, "", NULL, nbctl_init, NULL, "", RW }, { "sync", 0, 0, "", nbctl_pre_sync, nbctl_sync, NULL, "", RO }, - { "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO }, + { "show", 0, 1, "[SWITCH]", nbctl_pre_show, nbctl_show, NULL, "", RO }, /* logical switch commands. */ - { "ls-add", 0, 1, "[SWITCH]", NULL, nbctl_ls_add, NULL, + { "ls-add", 0, 1, "[SWITCH]", nbctl_pre_ls_add, nbctl_ls_add, NULL, "--may-exist,--add-duplicate", RW }, - { "ls-del", 1, 1, "SWITCH", NULL, nbctl_ls_del, NULL, "--if-exists", RW }, - { "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO }, + { "ls-del", 1, 1, "SWITCH", nbctl_pre_ls_del, nbctl_ls_del, NULL, "--if-exists", RW }, + { "ls-list", 0, 0, "", nbctl_pre_ls_list, nbctl_ls_list, NULL, "", RO }, /* acl commands. */ { "acl-add", 5, 6, "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION", - NULL, nbctl_acl_add, NULL, + nbctl_pre_acl, nbctl_acl_add, NULL, "--log,--may-exist,--type=,--name=,--severity=,--meter=", RW }, { "acl-del", 1, 4, "{SWITCH | PORTGROUP} [DIRECTION [PRIORITY MATCH]]", - NULL, nbctl_acl_del, NULL, "--type=", RW }, + nbctl_pre_acl, nbctl_acl_del, NULL, "--type=", RW }, { "acl-list", 1, 1, "{SWITCH | PORTGROUP}", - NULL, nbctl_acl_list, NULL, "--type=", RO }, + nbctl_pre_acl_list, nbctl_acl_list, NULL, "--type=", RO }, /* qos commands. */ { "qos-add", 5, 7, "SWITCH DIRECTION PRIORITY MATCH [rate=RATE [burst=BURST]] [dscp=DSCP]", - NULL, nbctl_qos_add, NULL, "--may-exist", RW }, - { "qos-del", 1, 4, "SWITCH [{DIRECTION | UUID} [PRIORITY MATCH]]", NULL, - nbctl_qos_del, NULL, "", RW }, - { "qos-list", 1, 1, "SWITCH", NULL, nbctl_qos_list, NULL, "", RO }, + nbctl_pre_qos_add, nbctl_qos_add, NULL, "--may-exist", RW }, + { "qos-del", 1, 4, "SWITCH [{DIRECTION | UUID} [PRIORITY MATCH]]", + nbctl_pre_qos_del, nbctl_qos_del, NULL, "", RW }, + { "qos-list", 1, 1, "SWITCH", nbctl_pre_qos_list, nbctl_qos_list, + NULL, "", RO }, /* meter commands. */ - { "meter-add", 4, 5, "NAME ACTION RATE UNIT [BURST]", NULL, + { "meter-add", 4, 5, "NAME ACTION RATE UNIT [BURST]", nbctl_pre_meter_add, nbctl_meter_add, NULL, "--fair", RW }, - { "meter-del", 0, 1, "[NAME]", NULL, nbctl_meter_del, NULL, "", RW }, - { "meter-list", 0, 0, "", NULL, nbctl_meter_list, NULL, "", RO }, + { "meter-del", 0, 1, "[NAME]", nbctl_pre_meter_del, nbctl_meter_del, + NULL, "", RW }, + { "meter-list", 0, 0, "", nbctl_pre_meter_list, nbctl_meter_list, + NULL, "", RO }, /* logical switch port commands. */ - { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add, - NULL, "--may-exist", RW }, - { "lsp-del", 1, 1, "PORT", NULL, nbctl_lsp_del, NULL, "--if-exists", RW }, - { "lsp-list", 1, 1, "SWITCH", NULL, nbctl_lsp_list, NULL, "", RO }, - { "lsp-get-parent", 1, 1, "PORT", NULL, nbctl_lsp_get_parent, NULL, - "", RO }, - { "lsp-get-tag", 1, 1, "PORT", NULL, nbctl_lsp_get_tag, NULL, "", RO }, - { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", NULL, - nbctl_lsp_set_addresses, NULL, "", RW }, - { "lsp-get-addresses", 1, 1, "PORT", NULL, nbctl_lsp_get_addresses, NULL, - "", RO }, - { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", NULL, - nbctl_lsp_set_port_security, NULL, "", RW }, - { "lsp-get-port-security", 1, 1, "PORT", NULL, + { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", + nbctl_pre_lsp_add, nbctl_lsp_add, NULL, "--may-exist", RW }, + { "lsp-del", 1, 1, "PORT", nbctl_pre_lsp_del, nbctl_lsp_del, + NULL, "--if-exists", RW }, + { "lsp-list", 1, 1, "SWITCH", nbctl_pre_lsp_list, nbctl_lsp_list, + NULL, "", RO }, + { "lsp-get-parent", 1, 1, "PORT", nbctl_pre_lsp_get_parent, + nbctl_lsp_get_parent, NULL, "", RO }, + { "lsp-get-tag", 1, 1, "PORT", nbctl_pre_lsp_get_tag, nbctl_lsp_get_tag, + NULL, "", RO }, + { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", + nbctl_pre_lsp_set_addresses, nbctl_lsp_set_addresses, NULL, "", RW }, + { "lsp-get-addresses", 1, 1, "PORT", nbctl_pre_lsp_get_addresses, + nbctl_lsp_get_addresses, NULL, "", RO }, + { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", + nbctl_pre_lsp_port_security, nbctl_lsp_set_port_security, + NULL, "", RW }, + { "lsp-get-port-security", 1, 1, "PORT", nbctl_pre_lsp_port_security, nbctl_lsp_get_port_security, NULL, "", RO }, - { "lsp-get-up", 1, 1, "PORT", NULL, nbctl_lsp_get_up, NULL, "", RO }, - { "lsp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lsp_set_enabled, + { "lsp-get-up", 1, 1, "PORT", nbctl_pre_lsp_get_up, nbctl_lsp_get_up, + NULL, "", RO }, + { "lsp-set-enabled", 2, 2, "PORT STATE", nbctl_pre_lsp_enabled, + nbctl_lsp_set_enabled, NULL, "", RW }, + { "lsp-get-enabled", 1, 1, "PORT", nbctl_pre_lsp_enabled, + nbctl_lsp_get_enabled, NULL, "", RO }, + { "lsp-set-type", 2, 2, "PORT TYPE", nbctl_pre_lsp_type, + nbctl_lsp_set_type, NULL, "", RW }, + { "lsp-get-type", 1, 1, "PORT", nbctl_pre_lsp_type, + nbctl_lsp_get_type, NULL, "", RO }, + { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", + nbctl_pre_lsp_options, nbctl_lsp_set_options, NULL, "", RW }, + { "lsp-get-options", 1, 1, "PORT", nbctl_pre_lsp_options, + nbctl_lsp_get_options, NULL, "", RO }, + { "lsp-set-dhcpv4-options", 1, 2, "PORT [DHCP_OPT_UUID]", + nbctl_pre_lsp_dhcpv4_options, nbctl_lsp_set_dhcpv4_options, NULL, "", RW }, - { "lsp-get-enabled", 1, 1, "PORT", NULL, nbctl_lsp_get_enabled, NULL, - "", RO }, - { "lsp-set-type", 2, 2, "PORT TYPE", NULL, nbctl_lsp_set_type, NULL, - "", RW }, - { "lsp-get-type", 1, 1, "PORT", NULL, nbctl_lsp_get_type, NULL, "", RO }, - { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", NULL, - nbctl_lsp_set_options, NULL, "", RW }, - { "lsp-get-options", 1, 1, "PORT", NULL, nbctl_lsp_get_options, NULL, - "", RO }, - { "lsp-set-dhcpv4-options", 1, 2, "PORT [DHCP_OPT_UUID]", NULL, - nbctl_lsp_set_dhcpv4_options, NULL, "", RW }, - { "lsp-get-dhcpv4-options", 1, 1, "PORT", NULL, + { "lsp-get-dhcpv4-options", 1, 1, "PORT", nbctl_pre_lsp_dhcpv4_options, nbctl_lsp_get_dhcpv4_options, NULL, "", RO }, - { "lsp-set-dhcpv6-options", 1, 2, "PORT [DHCP_OPT_UUID]", NULL, - nbctl_lsp_set_dhcpv6_options, NULL, "", RW }, - { "lsp-get-dhcpv6-options", 1, 1, "PORT", NULL, + { "lsp-set-dhcpv6-options", 1, 2, "PORT [DHCP_OPT_UUID]", + nbctl_pre_lsp_dhcpv6_options, nbctl_lsp_set_dhcpv6_options, + NULL, "", RW }, + { "lsp-get-dhcpv6-options", 1, 1, "PORT", nbctl_pre_lsp_dhcpv6_options, nbctl_lsp_get_dhcpv6_options, NULL, "", RO }, - { "lsp-get-ls", 1, 1, "PORT", NULL, nbctl_lsp_get_ls, NULL, "", RO }, + { "lsp-get-ls", 1, 1, "PORT", nbctl_pre_lsp_get_ls, nbctl_lsp_get_ls, + NULL, "", RO }, /* forwarding group commands. */ { "fwd-group-add", 4, INT_MAX, "SWITCH GROUP VIP VMAC PORT...", - NULL, nbctl_fwd_group_add, NULL, "--liveness", RW }, - { "fwd-group-del", 1, 1, "GROUP", NULL, nbctl_fwd_group_del, NULL, - "--if-exists", RW }, - { "fwd-group-list", 0, 1, "[GROUP]", NULL, nbctl_fwd_group_list, NULL, - "", RO }, + nbctl_pre_fwd_group_add, nbctl_fwd_group_add, NULL, "--liveness", RW }, + { "fwd-group-del", 1, 1, "GROUP", nbctl_pre_fwd_group_del, + nbctl_fwd_group_del, NULL, "--if-exists", RW }, + { "fwd-group-list", 0, 1, "[GROUP]", nbctl_pre_fwd_group_list, + nbctl_fwd_group_list, NULL, "", RO }, /* logical router commands. */ - { "lr-add", 0, 1, "[ROUTER]", NULL, nbctl_lr_add, NULL, + { "lr-add", 0, 1, "[ROUTER]", nbctl_pre_lr_add, nbctl_lr_add, NULL, "--may-exist,--add-duplicate", RW }, - { "lr-del", 1, 1, "ROUTER", NULL, nbctl_lr_del, NULL, "--if-exists", RW }, - { "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO }, + { "lr-del", 1, 1, "ROUTER", nbctl_pre_lr_del, nbctl_lr_del, + NULL, "--if-exists", RW }, + { "lr-list", 0, 0, "", nbctl_pre_lr_list, nbctl_lr_list, NULL, "", RO }, /* logical router port commands. */ { "lrp-add", 4, INT_MAX, "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...", - NULL, nbctl_lrp_add, NULL, "--may-exist", RW }, + nbctl_pre_lrp_add, nbctl_lrp_add, NULL, "--may-exist", RW }, { "lrp-set-gateway-chassis", 2, 3, "PORT CHASSIS [PRIORITY]", - NULL, nbctl_lrp_set_gateway_chassis, NULL, "--may-exist", RW }, - { "lrp-del-gateway-chassis", 2, 2, "PORT CHASSIS", NULL, - nbctl_lrp_del_gateway_chassis, NULL, "", RW }, - { "lrp-get-gateway-chassis", 1, 1, "PORT", NULL, - nbctl_lrp_get_gateway_chassis, NULL, "", RO }, - { "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW }, - { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO }, - { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled, + nbctl_pre_lrp_set_gateway_chassis, nbctl_lrp_set_gateway_chassis, + NULL, "--may-exist", RW }, + { "lrp-del-gateway-chassis", 2, 2, "PORT CHASSIS", + nbctl_pre_lrp_del_gateway_chassis, nbctl_lrp_del_gateway_chassis, NULL, "", RW }, - { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled, + { "lrp-get-gateway-chassis", 1, 1, "PORT", + nbctl_pre_lrp_get_gateway_chassis, nbctl_lrp_get_gateway_chassis, NULL, "", RO }, - { "lrp-set-redirect-type", 2, 2, "PORT TYPE", NULL, - nbctl_lrp_set_redirect_type, NULL, "", RW }, - { "lrp-get-redirect-type", 1, 1, "PORT", NULL, nbctl_lrp_get_redirect_type, + { "lrp-del", 1, 1, "PORT", nbctl_pre_lrp_del, nbctl_lrp_del, + NULL, "--if-exists", RW }, + { "lrp-list", 1, 1, "ROUTER", nbctl_pre_lrp_list, nbctl_lrp_list, NULL, "", RO }, + { "lrp-set-enabled", 2, 2, "PORT STATE", nbctl_pre_lrp_enabled, + nbctl_lrp_set_enabled, NULL, "", RW }, + { "lrp-get-enabled", 1, 1, "PORT", nbctl_pre_lrp_enabled, + nbctl_lrp_get_enabled, NULL, "", RO }, + { "lrp-set-redirect-type", 2, 2, "PORT TYPE", + nbctl_pre_lrp_redirect_type, nbctl_lrp_set_redirect_type, + NULL, "", RW }, + { "lrp-get-redirect-type", 1, 1, "PORT", nbctl_pre_lrp_redirect_type, + nbctl_lrp_get_redirect_type, NULL, "", RO }, /* logical router route commands. */ - { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL, - nbctl_lr_route_add, NULL, "--may-exist,--ecmp,--ecmp-symmetric-reply," - "--policy=,--bfd?", RW }, - { "lr-route-del", 1, 4, "ROUTER [PREFIX [NEXTHOP [PORT]]]", NULL, - nbctl_lr_route_del, NULL, "--if-exists,--policy=", RW }, - { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL, - "", RO }, + { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", + nbctl_pre_lr_route_add, nbctl_lr_route_add, NULL, + "--may-exist,--ecmp,--ecmp-symmetric-reply,--policy=,--bfd?", RW }, + { "lr-route-del", 1, 4, "ROUTER [PREFIX [NEXTHOP [PORT]]]", + nbctl_pre_lr_route_del, nbctl_lr_route_del, NULL, + "--if-exists,--policy=", RW }, + { "lr-route-list", 1, 1, "ROUTER", nbctl_pre_lr_route_list, + nbctl_lr_route_list, NULL, "", RO }, /* Policy commands */ { "lr-policy-add", 4, INT_MAX, "ROUTER PRIORITY MATCH ACTION [NEXTHOP] [OPTIONS - KEY=VALUE ...]", - NULL, nbctl_lr_policy_add, NULL, "--may-exist", RW }, - { "lr-policy-del", 1, 3, "ROUTER [{PRIORITY | UUID} [MATCH]]", NULL, - nbctl_lr_policy_del, NULL, "--if-exists", RW }, - { "lr-policy-list", 1, 1, "ROUTER", NULL, nbctl_lr_policy_list, NULL, - "", RO }, + nbctl_pre_lr_policy_add, nbctl_lr_policy_add, NULL, "--may-exist", RW }, + { "lr-policy-del", 1, 3, "ROUTER [{PRIORITY | UUID} [MATCH]]", + nbctl_pre_lr_policy_del, nbctl_lr_policy_del, NULL, "--if-exists", RW }, + { "lr-policy-list", 1, 1, "ROUTER", nbctl_pre_lr_policy_list, + nbctl_lr_policy_list, NULL, "", RO }, /* NAT commands. */ { "lr-nat-add", 4, 7, "ROUTER TYPE EXTERNAL_IP LOGICAL_IP" - "[LOGICAL_PORT EXTERNAL_MAC] [EXTERNAL_PORT_RANGE]", NULL, - nbctl_lr_nat_add, NULL, "--may-exist,--stateless,--portrange", RW }, - { "lr-nat-del", 1, 3, "ROUTER [TYPE [IP]]", NULL, - nbctl_lr_nat_del, NULL, "--if-exists", RW }, - { "lr-nat-list", 1, 1, "ROUTER", NULL, nbctl_lr_nat_list, NULL, "", RO }, - { "lr-nat-update-ext-ip", 4, 4, "ROUTER TYPE IP ADDRESS_SET", NULL, - nbctl_lr_nat_set_ext_ips, NULL, "--is-exempted", RW}, + "[LOGICAL_PORT EXTERNAL_MAC] [EXTERNAL_PORT_RANGE]", + nbctl_pre_lr_nat_add, nbctl_lr_nat_add, + NULL, "--may-exist,--stateless,--portrange", RW }, + { "lr-nat-del", 1, 3, "ROUTER [TYPE [IP]]", + nbctl_pre_lr_nat_del, nbctl_lr_nat_del, NULL, "--if-exists", RW }, + { "lr-nat-list", 1, 1, "ROUTER", nbctl_pre_lr_nat_list, + nbctl_lr_nat_list, NULL, "", RO }, + { "lr-nat-update-ext-ip", 4, 4, "ROUTER TYPE IP ADDRESS_SET", + nbctl_pre_lr_nat_set_ext_ips, nbctl_lr_nat_set_ext_ips, + NULL, "--is-exempted", RW}, /* load balancer commands. */ - { "lb-add", 3, 4, "LB VIP[:PORT] IP[:PORT]... [PROTOCOL]", NULL, - nbctl_lb_add, NULL, "--may-exist,--add-duplicate,--reject,--event", RW }, - { "lb-del", 1, 2, "LB [VIP]", NULL, nbctl_lb_del, NULL, - "--if-exists", RW }, - { "lb-list", 0, 1, "[LB]", NULL, nbctl_lb_list, NULL, "", RO }, - { "lr-lb-add", 2, 2, "ROUTER LB", NULL, nbctl_lr_lb_add, NULL, - "--may-exist", RW }, - { "lr-lb-del", 1, 2, "ROUTER [LB]", NULL, nbctl_lr_lb_del, NULL, + { "lb-add", 3, 4, "LB VIP[:PORT] IP[:PORT]... [PROTOCOL]", + nbctl_pre_lb_add, nbctl_lb_add, NULL, + "--may-exist,--add-duplicate,--reject,--event", RW }, + { "lb-del", 1, 2, "LB [VIP]", nbctl_pre_lb_del, nbctl_lb_del, NULL, "--if-exists", RW }, - { "lr-lb-list", 1, 1, "ROUTER", NULL, nbctl_lr_lb_list, NULL, - "", RO }, - { "ls-lb-add", 2, 2, "SWITCH LB", NULL, nbctl_ls_lb_add, NULL, - "--may-exist", RW }, - { "ls-lb-del", 1, 2, "SWITCH [LB]", NULL, nbctl_ls_lb_del, NULL, - "--if-exists", RW }, - { "ls-lb-list", 1, 1, "SWITCH", NULL, nbctl_ls_lb_list, NULL, - "", RO }, + { "lb-list", 0, 1, "[LB]", nbctl_pre_lb_list, nbctl_lb_list, NULL, "", RO }, + { "lr-lb-add", 2, 2, "ROUTER LB", nbctl_pre_lr_lb_add, + nbctl_lr_lb_add, NULL, "--may-exist", RW }, + { "lr-lb-del", 1, 2, "ROUTER [LB]", nbctl_pre_lr_lb_del, + nbctl_lr_lb_del, NULL, "--if-exists", RW }, + { "lr-lb-list", 1, 1, "ROUTER", nbctl_pre_lr_lb_list, + nbctl_lr_lb_list, NULL, "", RO }, + { "ls-lb-add", 2, 2, "SWITCH LB", nbctl_pre_ls_lb_add, + nbctl_ls_lb_add, NULL, "--may-exist", RW }, + { "ls-lb-del", 1, 2, "SWITCH [LB]", nbctl_pre_ls_lb_del, + nbctl_ls_lb_del, NULL, "--if-exists", RW }, + { "ls-lb-list", 1, 1, "SWITCH", nbctl_pre_ls_lb_list, nbctl_ls_lb_list, + NULL, "", RO }, /* DHCP_Options commands */ - {"dhcp-options-create", 1, INT_MAX, "CIDR [EXTERNAL:IDS]", NULL, - nbctl_dhcp_options_create, NULL, "", RW }, - {"dhcp-options-del", 1, 1, "DHCP_OPT_UUID", NULL, + {"dhcp-options-create", 1, INT_MAX, "CIDR [EXTERNAL:IDS]", + NULL, nbctl_dhcp_options_create, NULL, "", RW }, + {"dhcp-options-del", 1, 1, "DHCP_OPT_UUID", nbctl_pre_dhcp_options_del, nbctl_dhcp_options_del, NULL, "", RW}, - {"dhcp-options-list", 0, 0, "", NULL, nbctl_dhcp_options_list, NULL, "", RO}, + {"dhcp-options-list", 0, 0, "", nbctl_pre_dhcp_options_list, + nbctl_dhcp_options_list, NULL, "", RO}, {"dhcp-options-set-options", 1, INT_MAX, "DHCP_OPT_UUID KEY=VALUE [KEY=VALUE]...", - NULL, nbctl_dhcp_options_set_options, NULL, "", RW }, - {"dhcp-options-get-options", 1, 1, "DHCP_OPT_UUID", NULL, - nbctl_dhcp_options_get_options, NULL, "", RO }, + nbctl_pre_dhcp_options_options, nbctl_dhcp_options_set_options, + NULL, "", RW }, + {"dhcp-options-get-options", 1, 1, "DHCP_OPT_UUID", + nbctl_pre_dhcp_options_options, nbctl_dhcp_options_get_options, + NULL, "", RO }, /* Connection commands. */ {"get-connection", 0, 0, "", pre_connection, cmd_get_connection, NULL, "", RO}, @@ -5959,23 +6727,25 @@ static const struct ctl_command_syntax nbctl_commands[] = { pre_cmd_set_ssl, cmd_set_ssl, NULL, "--bootstrap", RW}, /* Port Group Commands */ - {"pg-add", 1, INT_MAX, "", NULL, cmd_pg_add, NULL, "", RW }, - {"pg-set-ports", 2, INT_MAX, "", NULL, cmd_pg_set_ports, NULL, "", RW }, - {"pg-del", 1, 1, "", NULL, cmd_pg_del, NULL, "", RW }, + {"pg-add", 1, INT_MAX, "", cmd_pre_pg_add, cmd_pg_add, NULL, "", RW }, + {"pg-set-ports", 2, INT_MAX, "", cmd_pre_pg_set_ports, cmd_pg_set_ports, + NULL, "", RW }, + {"pg-del", 1, 1, "", cmd_pre_pg_del, cmd_pg_del, NULL, "", RW }, /* HA chassis group commands. */ - {"ha-chassis-group-add", 1, 1, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_add, NULL, "", RW }, - {"ha-chassis-group-del", 1, 1, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_del, NULL, "", RW }, - {"ha-chassis-group-list", 0, 0, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_list, NULL, "", RO }, - {"ha-chassis-group-add-chassis", 3, 3, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_add_chassis, NULL, "", RW }, - {"ha-chassis-group-remove-chassis", 2, 2, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_remove_chassis, NULL, "", RW }, - {"ha-chassis-group-set-chassis-prio", 3, 3, "[CHASSIS GROUP]", NULL, - cmd_ha_ch_grp_set_chassis_prio, NULL, "", RW }, + {"ha-chassis-group-add", 1, 1, "[CHASSIS GROUP]", + NULL, cmd_ha_ch_grp_add, NULL, "", RW }, + {"ha-chassis-group-del", 1, 1, "[CHASSIS GROUP]", + pre_ha_ch_grp_del, cmd_ha_ch_grp_del, NULL, "", RW }, + {"ha-chassis-group-list", 0, 0, "[CHASSIS GROUP]", + pre_ha_ch_grp_list, cmd_ha_ch_grp_list, NULL, "", RO }, + {"ha-chassis-group-add-chassis", 3, 3, "[CHASSIS GROUP]", + pre_ha_ch_grp_add_chassis, cmd_ha_ch_grp_add_chassis, NULL, "", RW }, + {"ha-chassis-group-remove-chassis", 2, 2, "[CHASSIS GROUP]", + pre_ha_ch_grp_remove_chassis, cmd_ha_ch_grp_remove_chassis, NULL, "", RW }, + {"ha-chassis-group-set-chassis-prio", 3, 3, "[CHASSIS GROUP]", + pre_ha_ch_grp_set_chassis_prio, cmd_ha_ch_grp_set_chassis_prio, NULL, + "", RW }, {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO}, }; From patchwork Fri May 7 04:06:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475319 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxk626ckz9sPf for ; Fri, 7 May 2021 14:07:41 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C6E14404FC; Fri, 7 May 2021 04:07:39 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id u27NMWVQtNd5; Fri, 7 May 2021 04:07:38 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTP id C5D324050D; Fri, 7 May 2021 04:07:35 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0F109C002B; Fri, 7 May 2021 04:07:35 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CE1BC000F for ; Fri, 7 May 2021 04:07:32 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id D14F540387 for ; Fri, 7 May 2021 04:07:25 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4yDrcMinHGhJ for ; Fri, 7 May 2021 04:07:24 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id C6F4640379 for ; Fri, 7 May 2021 04:07:23 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 58071C0004; Fri, 7 May 2021 04:07:21 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:42 -0700 Message-Id: <20210507040659.26830-11-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 10/27] tests: Miscellaneous debuggability improvements. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Ben Pfaff --- tests/ovn.at | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index 175cce0049cd..8adaaa9fde64 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -9683,9 +9683,10 @@ wait_for_ports_up check ovn-nbctl --wait=hv sync as hv1 ovs-vsctl show -echo "*************************" -ovn-sbctl list DNS -echo "*************************" +ovn-sbctl list DNS > dns +AT_CAPTURE_FILE([dns]) +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) reset_pcap_file() { local iface=$1 @@ -9879,8 +9880,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Try vm1 again but an all-caps query name - +AS_BOX([Try vm1 again but an all-caps query name]) set_dns_params VM1 src_ip=`ip_to_hex 10 0 0 6` dst_ip=`ip_to_hex 10 0 0 1` @@ -9902,8 +9902,12 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Clear the query name options for ls1-lp2 +AS_BOX([Clear the query name options for ls1-lp2]) ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org +ovn-sbctl list DNS > dns2 +AT_CAPTURE_FILE([dns2]) +ovn-sbctl dump-flows > sbflows2 +AT_CAPTURE_FILE([sbflows2]) set_dns_params vm2 src_ip=`ip_to_hex 10 0 0 4` @@ -9922,10 +9926,14 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Clear the query name for ls1-lp1 +AS_BOX([Clear the query name for ls1-lp1]) # Since ls1 has no query names configued, # ovn-northd should not add the DNS flows. ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org +ovn-sbctl list DNS > dns3 +AT_CAPTURE_FILE([dns3]) +ovn-sbctl dump-flows > sbflows3 +AT_CAPTURE_FILE([sbflows3]) set_dns_params vm1 src_ip=`ip_to_hex 10 0 0 6` @@ -9944,9 +9952,13 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Test IPv6 (AAAA records) using IPv4 packet. +AS_BOX([Test IPv6 (AAAA records) using IPv4 packet.]) # Add back the DNS options for ls1-lp1. ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4" +ovn-sbctl list DNS > dns4 +AT_CAPTURE_FILE([dns4]) +ovn-sbctl dump-flows > sbflows4 +AT_CAPTURE_FILE([sbflows4]) set_dns_params vm1_ipv6_only src_ip=`ip_to_hex 10 0 0 6` @@ -9969,7 +9981,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet. +AS_BOX([Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.]) set_dns_params vm1_ipv4_v6 src_ip=`ip_to_hex 10 0 0 6` dst_ip=`ip_to_hex 10 0 0 1` @@ -9991,7 +10003,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Invalid type. +AS_BOX([Invalid type]) set_dns_params vm1_invalid_type src_ip=`ip_to_hex 10 0 0 6` dst_ip=`ip_to_hex 10 0 0 1` @@ -10009,7 +10021,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Incomplete DNS packet. +AS_BOX([Incomplete DNS packet]) set_dns_params vm1_incomplete src_ip=`ip_to_hex 10 0 0 6` dst_ip=`ip_to_hex 10 0 0 1` @@ -10027,8 +10039,12 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Add one more DNS record to the ls1. +AS_BOX([Add one more DNS record to the ls1]) ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2" +ovn-sbctl list DNS > dns5 +AT_CAPTURE_FILE([dns5]) +ovn-sbctl dump-flows > sbflows5 +AT_CAPTURE_FILE([sbflows5]) set_dns_params vm3 src_ip=`ip_to_hex 10 0 0 4` @@ -10051,7 +10067,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected -# Try DNS query over IPv6 +AS_BOX([Try DNS query over IPv6]) set_dns_params vm1 src_ip=aef00000000000000000000000000004 dst_ip=aef00000000000000000000000000001 @@ -11176,10 +11192,10 @@ check ovn-nbctl --wait=hv sync # Check that there is a logical flow in logical switch foo's pipeline # to set the outport to rp-foo with the condition is_chassis_redirect. -ovn-sbctl dump-flows foo > sbflows +OVS_WAIT_UNTIL([ovn-sbctl dump-flows foo > sbflows + test 1 = `grep ls_in_l2_lkup sbflows | \ + grep rp-foo | grep is_chassis_resident | grep priority=50 -c`]) AT_CAPTURE_FILE([sbflows]) -OVS_WAIT_UNTIL([test 1 = `grep ls_in_l2_lkup sbflows | \ -grep rp-foo | grep is_chassis_resident | grep priority=50 -c`]) (echo "---------NB dump-----" ovn-nbctl show @@ -11256,9 +11272,12 @@ options:rxq_pcap=dummy-rx.pcap options:rxq_pcap=${pcap_file}-rx.pcap } +as hv1 ovs-appctl dpif/del-flows + as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2 as hv3 reset_pcap_file hv3-vif1 hv3/vif1 as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet +as hv1 ovs-appctl ofproto/trace br-int in_port=hv1-vif1 $packet sleep 2 # On hv1, table 37 check that no packet goes via the tunnel port From patchwork Fri May 7 04:06:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475321 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxkQ5tf3z9sPf for ; Fri, 7 May 2021 14:07:58 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id A91614049F; Fri, 7 May 2021 04:07:55 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GL8hcJBuZFr6; Fri, 7 May 2021 04:07:53 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id 5C73240542; Fri, 7 May 2021 04:07:49 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3A14AC0022; Fri, 7 May 2021 04:07:49 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3F035C0022 for ; Fri, 7 May 2021 04:07:48 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id B2CD3404BE for ; Fri, 7 May 2021 04:07:26 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id f10Nb0WZlnoC for ; Fri, 7 May 2021 04:07:26 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 89BD0404AD for ; Fri, 7 May 2021 04:07:25 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id B9620C0009; Fri, 7 May 2021 04:07:22 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:43 -0700 Message-Id: <20210507040659.26830-12-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 11/27] ovn-northd-ddlog: Upgrade to ddlog 0.38. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Upcoming commits will use a new --intern-table option of ovsdb2ddlog, so we need to upgrade to the version of ddlog that has that feature. To do so, we need to adapt the code to language changes in ddlog. This commit does that for a change in 0.37 in which, when iterating over a `Group` in a for-loop, the iterator returns `(value, weight)` tuples. This also adapts ovn-northd-ddlog.c to a slightly updated C API. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- NEWS | 2 +- northd/lrouter.dl | 2 +- northd/ovn-northd-ddlog.c | 21 +++++++++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 67c8b5f8bb38..b8efc28def60 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,7 @@ Post-v21.03.0 needed for the southbound database when northbound changes occur. It is expected to scale better than the C implementation, for large deployments. (This may take testing and tuning to be effective.) This version of OVN - requires DDLog 0.36. + requires DDLog 0.38. - Introduce ovn-controller incremental processing engine statistics - Introduced parallel processing in ovn-northd with the NB_Global config option 'use_parallel_build' to enable it. It is disabled by default. diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 312ceb9fcd12..f5738b2cc81d 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -392,7 +392,7 @@ LogicalRouterSnatIP(lr, snat_ip, Some{nat}) :- function group_to_setunionmap(g: Group<'K1, ('K2,Set<'V>)>): Map<'K2,Set<'V>> { var map = map_empty(); - for (entry in g) { + for ((entry, _) in g) { (var key, var value) = entry; match (map.get(key)) { None -> map.insert(key, value), diff --git a/northd/ovn-northd-ddlog.c b/northd/ovn-northd-ddlog.c index ca1ab325448c..74f0eaccd5bb 100644 --- a/northd/ovn-northd-ddlog.c +++ b/northd/ovn-northd-ddlog.c @@ -79,10 +79,11 @@ static table_id WARNING_TABLE_ID; static table_id NB_CFG_TIMESTAMP_ID; /* Initialize frequently used table ids. */ -static void init_table_ids(void) +static void +init_table_ids(ddlog_prog ddlog) { - WARNING_TABLE_ID = ddlog_get_table_id("helpers::Warning"); - NB_CFG_TIMESTAMP_ID = ddlog_get_table_id("NbCfgTimestamp"); + WARNING_TABLE_ID = ddlog_get_table_id(ddlog, "helpers::Warning"); + NB_CFG_TIMESTAMP_ID = ddlog_get_table_id(ddlog, "NbCfgTimestamp"); } struct northd_ctx { @@ -347,7 +348,8 @@ ddlog_clear(struct northd_ctx *ctx) int n_failures = 0; for (int i = 0; ctx->input_relations[i]; i++) { char *table = xasprintf("%s%s", ctx->prefix, ctx->input_relations[i]); - if (ddlog_clear_relation(ctx->ddlog, ddlog_get_table_id(table))) { + if (ddlog_clear_relation(ctx->ddlog, ddlog_get_table_id(ctx->ddlog, + table))) { n_failures++; } free(table); @@ -611,7 +613,7 @@ northd_update_probe_interval(struct northd_ctx *nb, struct northd_ctx *sb) * Any other value is an explicit probe interval request from the * database. */ int probe_interval = 0; - table_id tid = ddlog_get_table_id("Northd_Probe_Interval"); + table_id tid = ddlog_get_table_id(nb->ddlog, "Northd_Probe_Interval"); ddlog_delta *probe_delta = ddlog_delta_remove_table(nb->delta, tid); ddlog_delta_enumerate(probe_delta, northd_update_probe_interval_cb, (uintptr_t) &probe_interval); ddlog_free_delta(probe_delta); @@ -670,7 +672,7 @@ ddlog_table_update_output(struct ds *ds, ddlog_prog ddlog, ddlog_delta *delta, return; } char *table_name = xasprintf("%s::Out_%s", db, table); - ddlog_delta_clear_table(delta, ddlog_get_table_id(table_name)); + ddlog_delta_clear_table(delta, ddlog_get_table_id(ddlog, table_name)); free(table_name); if (!updates[0]) { @@ -948,7 +950,7 @@ get_database_ops(struct northd_ctx *ctx) * We require output-only tables to have an accompanying index * named _Index. */ char *index = xasprintf("%s_Index", table); - index_id idxid = ddlog_get_index_id(index); + index_id idxid = ddlog_get_index_id(ctx->ddlog, index); if (idxid == -1) { VLOG_WARN_RL(&rl, "%s: unknown index", index); free(index); @@ -1000,7 +1002,7 @@ get_database_ops(struct northd_ctx *ctx) static int64_t old_sb_cfg_timestamp = INT64_MIN; int64_t new_sb_cfg = old_sb_cfg; if (ctx->has_timestamp_columns) { - table_id sb_cfg_tid = ddlog_get_table_id("SbCfg"); + table_id sb_cfg_tid = ddlog_get_table_id(ctx->ddlog, "SbCfg"); ddlog_delta *sb_cfg_delta = ddlog_delta_remove_table(ctx->delta, sb_cfg_tid); ddlog_delta_enumerate(sb_cfg_delta, northd_update_sb_cfg_cb, @@ -1149,8 +1151,6 @@ main(int argc, char *argv[]) int retval; bool exiting; - init_table_ids(); - fatal_ignore_sigpipe(); ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); @@ -1180,6 +1180,7 @@ main(int argc, char *argv[]) if (!ddlog) { ovs_fatal(0, "DDlog instance could not be created"); } + init_table_ids(ddlog); unixctl_command_register("enable-cpu-profiling", "", 0, 0, ovn_northd_enable_cpu_profiling, ddlog); From patchwork Fri May 7 04:06:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475324 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxkh2ZVnz9sPf for ; Fri, 7 May 2021 14:08:12 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 62AC66F652; Fri, 7 May 2021 04:08:09 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1CpyvX20RgFI; Fri, 7 May 2021 04:08:07 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id 0CC496162C; Fri, 7 May 2021 04:07:55 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id A070CC002A; Fri, 7 May 2021 04:07:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 35029C0028 for ; Fri, 7 May 2021 04:07:53 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 6E932404AD for ; Fri, 7 May 2021 04:07:28 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6KyhKPVd9qFl for ; Fri, 7 May 2021 04:07:27 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 47A09404EC for ; Fri, 7 May 2021 04:07:26 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 7D7AEC0007; Fri, 7 May 2021 04:07:24 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:44 -0700 Message-Id: <20210507040659.26830-13-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff , Dumitru Ceara Subject: [ovs-dev] [PATCH ovn v3 12/27] ovn-northd-ddlog: Preserve NB_Global more carefully. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Dumitru reported in #openvswitch that ovn-northd-ddlog can discard the setting of NB_Global.options:use_logical_dp_groups at startup. I think that this must be because it seems possible that at startup some of the relations in the Out_NB_Global rule aren't populated yet, and yet there is still a row in nb::NB_Global, so that neither rule for Out_NB_Global matches and therefore ovn-northd-ddlog deletes the row. This commit changes the structure of how ovn-northd-ddlog generates Out_NB_Global to ensure that, if there's an input row, it always generates exactly one output row. This should be more robust than the previous version regardless of whether it fixes the exact problem that Dumitru observed (which I did not try to reproduce). Reported-by: Dumitru Ceara Signed-off-by: Ben Pfaff --- northd/ovn_northd.dl | 63 ++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index ffd09c35f51b..6b45df739c67 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -633,21 +633,25 @@ HvCfgTimestamp(hv_cfg_timestamp) :- not HvCfgTimestamp0(). /* - * NB_Global: - * - set `sb_cfg` to the value of `SB_Global.nb_cfg`. - * - set `hv_cfg` to the smallest value of `nb_cfg` across all `Chassis` - * - FIXME: we use ipsec as unique key to make sure that we don't create multiple `NB_Global` - * instance. There is a potential race condition if this field is modified at the same - * time northd is updating `sb_cfg` or `hv_cfg`. + * nb::Out_NB_Global. + * + * OutNBGlobal0 generates the new record in the common case. + * OutNBGlobal1 generates the new record as a copy of nb::NB_Global, if sb::SB_Global is missing. + * nb::Out_NB_Global makes sure we have only a single record in the relation. + * + * (We don't generate an NB_Global output record if there isn't + * one in the input. We don't have enough entropy available to + * generate a random _uuid. Doesn't seem like a big deal, because + * OVN probably hasn't really been initialized yet.) */ -input relation NbCfgTimestamp[integer] -nb::Out_NB_Global(._uuid = _uuid, - .sb_cfg = sb_cfg, - .hv_cfg = hv_cfg, - .nb_cfg_timestamp = nb_cfg_timestamp, - .hv_cfg_timestamp = hv_cfg_timestamp, - .ipsec = ipsec, - .options = options) :- +relation OutNBGlobal0[nb::Out_NB_Global] +OutNBGlobal0[nb::Out_NB_Global{._uuid = _uuid, + .sb_cfg = sb_cfg, + .hv_cfg = hv_cfg, + .nb_cfg_timestamp = nb_cfg_timestamp, + .hv_cfg_timestamp = hv_cfg_timestamp, + .ipsec = ipsec, + .options = options}] :- NbCfgTimestamp[nb_cfg_timestamp], HvCfgTimestamp(hv_cfg_timestamp), nbg in nb::NB_Global(._uuid = _uuid, .ipsec = ipsec), @@ -662,19 +666,26 @@ nb::Out_NB_Global(._uuid = _uuid, var options2 = options1.insert_imm("max_tunid", "${max_tunid}"), var options = options2.insert_imm("northd_internal_version", ovn_internal_version()). +relation OutNBGlobal1[nb::Out_NB_Global] +OutNBGlobal1[x] :- OutNBGlobal0[x]. +OutNBGlobal1[nb::Out_NB_Global{._uuid = nbg._uuid, + .sb_cfg = nbg.sb_cfg, + .hv_cfg = nbg.hv_cfg, + .ipsec = nbg.ipsec, + .options = nbg.options, + .nb_cfg_timestamp = nbg.nb_cfg_timestamp, + .hv_cfg_timestamp = nbg.hv_cfg_timestamp}] :- + Unit(), + not OutNBGlobal0[_], + nbg in nb::NB_Global(). + +nb::Out_NB_Global[y] :- + OutNBGlobal1[x], + var y = x.group_by(()).group_first(). -/* SB_Global does not exist yet -- just keep the old value of NB_Global */ -nb::Out_NB_Global(._uuid = nbg._uuid, - .sb_cfg = nbg.sb_cfg, - .hv_cfg = nbg.hv_cfg, - .ipsec = nbg.ipsec, - .options = nbg.options, - .nb_cfg_timestamp = nb_cfg_timestamp, - .hv_cfg_timestamp = hv_cfg_timestamp) :- - NbCfgTimestamp[nb_cfg_timestamp], - HvCfgTimestamp(hv_cfg_timestamp), - nbg in nb::NB_Global(), - not sb::SB_Global(). +// Tracks the value that should go into NB_Global's 'nb_cfg_timestamp' column. +// ovn-northd-ddlog.c pushes the current time directly into this relation. +input relation NbCfgTimestamp[integer] output relation SbCfg[integer] SbCfg[sb_cfg] :- nb::Out_NB_Global(.sb_cfg = sb_cfg). From patchwork Fri May 7 04:06:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475326 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxl2632cz9sPf for ; Fri, 7 May 2021 14:08:30 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 21CFF8448C; Fri, 7 May 2021 04:08:28 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OYID7GxE3EBc; Fri, 7 May 2021 04:08:17 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id 027F6843AB; Fri, 7 May 2021 04:07:56 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9B092C0011; Fri, 7 May 2021 04:07:55 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0FF53C002A for ; Fri, 7 May 2021 04:07:54 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A2B3E40381 for ; Fri, 7 May 2021 04:07:32 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id umi5TxAutLEY for ; Fri, 7 May 2021 04:07:29 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1CA634038C for ; Fri, 7 May 2021 04:07:28 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 3ABCEC0004; Fri, 7 May 2021 04:07:25 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:45 -0700 Message-Id: <20210507040659.26830-14-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 13/27] ovn-northd-ddlog: Remove `lr` field from `Router`. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk `relation Router` stores the internal representation of a logical router, consisting of values from the `nb::Logical_Router` table augmented with some additional fields. We used to do this by copying the entire `Logical_Router` record inside `Router`. This proved highly inefficient in scenarios where the set of router ports changes frequently. Every such change modifies the `ports` array inside `Logical_Router`, which triggers an update of the `Router` object, which can cause a bunch of rules to update their outputs. This recomputation is unnecessary as none of these rules look at the `ports` field (`ports` is a slightly backwards way to maintain the relationship between ports and routers by storing the array of ports in the router instead of having each port point to the router). As a workaround, we no longer store the entire `Logical_Router` object in the `Router` table, and instead only copy its relevant fields. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 47 ++++-- northd/ovn_northd.dl | 370 +++++++++++++++++++++---------------------- 2 files changed, 218 insertions(+), 199 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index f5738b2cc81d..07579fb45902 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -329,10 +329,10 @@ LogicalRouterNATs(lr, vec_empty()) :- nb::Logical_Router(._uuid = lr), not LogicalRouterNAT(lr, _). -function get_force_snat_ip(lr: nb::Logical_Router, key_type: string): Set = +function get_force_snat_ip(options: Map, key_type: string): Set = { var ips = set_empty(); - match (lr.options.get(key_type ++ "_force_snat_ip")) { + match (options.get(key_type ++ "_force_snat_ip")) { None -> (), Some{s} -> { for (token in s.split(" ")) { @@ -346,8 +346,8 @@ function get_force_snat_ip(lr: nb::Logical_Router, key_type: string): Set, key_type: string): bool { + not get_force_snat_ip(options, key_type).is_empty() } function lb_force_snat_router_ip(lr_options: Map): bool { @@ -359,11 +359,11 @@ typedef LBForceSNAT = NoForceSNAT | ForceSNAT | SkipSNAT -function snat_for_lb(lr: nb::Logical_Router, lb: Ref): LBForceSNAT { +function snat_for_lb(lr_options: Map, lb: Ref): LBForceSNAT { if (lb.options.get_bool_def("skip_snat", false)) { return SkipSNAT }; - if (not get_force_snat_ip(lr, "lb").is_empty() or lb_force_snat_router_ip(lr.options)) { + if (not get_force_snat_ip(lr_options, "lb").is_empty() or lb_force_snat_router_ip(lr_options)) { return ForceSNAT }; return NoForceSNAT @@ -380,11 +380,11 @@ function snat_for_lb(lr: nb::Logical_Router, lb: Ref): LBForc relation LogicalRouterSnatIP(lr: uuid, snat_ip: v46_ip, nat: Option) LogicalRouterSnatIP(lr._uuid, force_snat_ip, None) :- lr in nb::Logical_Router(), - var dnat_force_snat_ips = get_force_snat_ip(lr, "dnat"), + var dnat_force_snat_ips = get_force_snat_ip(lr.options, "dnat"), var lb_force_snat_ips = if (lb_force_snat_router_ip(lr.options)) { set_empty() } else { - get_force_snat_ip(lr, "lb") + get_force_snat_ip(lr.options, "lb") }, var force_snat_ip = FlatMap(dnat_force_snat_ips.union(lb_force_snat_ips)). LogicalRouterSnatIP(lr, snat_ip, Some{nat}) :- @@ -428,7 +428,6 @@ LogicalRouterLBs(lr, vec_empty()) :- /* Router relation collects all attributes of a logical router. * - * `lr` - Logical_Router record from the NB database * `l3dgw_port` - optional redirect port (see `DistributedGatewayPort`) * `redirect_port_name` - derived redirect port name (or empty string if * router does not have a redirect port) @@ -442,7 +441,18 @@ LogicalRouterLBs(lr, vec_empty()) :- function chassis_redirect_name(port_name: string): string = "cr-${port_name}" relation &Router( - lr: nb::Logical_Router, + /* Fields copied from nb::Logical_Router. */ + _uuid: uuid, + name: string, + static_routes: Set, + policies: Set, + enabled: Option, + nat: Set, + load_balancer: Set, + options: Map, + external_ids: Map, + + /* Additional computed fields. */ l3dgw_port: Option, redirect_port_name: string, is_gateway: bool, @@ -454,7 +464,16 @@ relation &Router( force_lb_snat: bool, ) -&Router(.lr = lr, +&Router(._uuid = lr._uuid, + .name = lr.name, + .static_routes = lr.static_routes, + .policies = lr.policies, + .enabled = lr.enabled, + .nat = lr.nat, + .load_balancer = lr.load_balancer, + .options = lr.options, + .external_ids = lr.external_ids, + .l3dgw_port = l3dgw_port, .redirect_port_name = match (l3dgw_port) { @@ -586,7 +605,7 @@ relation &RouterPort( nb::Logical_Router_Port[lrp], Some{var networks} = extract_lrp_networks(lrp.mac, lrp.networks), LogicalRouterPort(lrp._uuid, lrouter_uuid), - router in &Router(.lr = nb::Logical_Router{._uuid = lrouter_uuid}), + router in &Router(._uuid = lrouter_uuid), RouterPortIsRedirect(lrp._uuid, is_redirect), RouterPortPeer(lrp._uuid, peer), mcast_cfg in &McastPortCfg(.port = lrp._uuid, .router_port = true), @@ -713,7 +732,7 @@ RouterStaticRoute_(.router = router, .nexthop = route.nexthop, .output_port = route.output_port, .ecmp_symmetric_reply = route.ecmp_symmetric_reply) :- - router in &Router(.lr = nb::Logical_Router{.static_routes = routes}), + router in &Router(.static_routes = routes), var route_id = FlatMap(routes), route in &StaticRoute(.lrsr = nb::Logical_Router_Static_Route{._uuid = route_id}). @@ -734,7 +753,7 @@ RouterStaticRoute(router, key, dsts) :- rsr in RouterStaticRoute_(.router = router, .output_port = None), /* output_port is not specified, find the * router port matching the next hop. */ - port in &RouterPort(.router = &Router{.lr = nb::Logical_Router{._uuid = router.lr._uuid}}, + port in &RouterPort(.router = &Router{._uuid = router._uuid}, .networks = networks), Some{var src_ip} = find_lrp_member_ip(networks, rsr.nexthop), var dst = RouteDst{rsr.nexthop, src_ip, port, rsr.ecmp_symmetric_reply}, diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 6b45df739c67..fad633b1870e 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -180,8 +180,8 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, eids }, Some{var router_port} = lsp.options.get("router-port"), - var opt_chassis = peer.and_then(|p| p.router.lr.options.get("chassis")), - var l3dgw_port = peer.and_then(|p| p.router.l3dgw_port), + var opt_chassis = peer.and_then(|p| p.router.options.get("chassis")), + var l3dgw_port = peer.and_then(|p| p.router.l3dgw_port), (var __type, var options) = { var options = ["peer" -> router_port]; match (opt_chassis) { @@ -238,7 +238,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, (rport.lrp.options.get_bool_def("reside-on-redirect-chassis", false) and l3dgw_port.is_some()) or Some{rport.lrp} == l3dgw_port or - (rport.router.lr.options.contains_key("chassis") and + (rport.router.options.contains_key("chassis") and not sw.localnet_ports.is_empty())) { false -> set_empty(), true -> set_singleton(get_garp_nat_addresses(deref(rport))) @@ -254,7 +254,7 @@ OutProxy_Port_Binding(._uuid = lrp._uuid, .gateway_chassis = set_empty(), .ha_chassis_group = None, .options = options, - .datapath = router.lr._uuid, + .datapath = router._uuid, .parent_port = None, .tag = None, // always empty for router ports .mac = set_singleton("${lrp.mac} ${lrp.networks.join(\" \")}"), @@ -262,7 +262,7 @@ OutProxy_Port_Binding(._uuid = lrp._uuid, .external_ids = lrp.external_ids) :- rp in &RouterPort(.lrp = lrp, .router = &router, .peer = peer), RouterPortRAOptionsComplete(lrp._uuid, options0), - (var __type, var options1) = match (router.lr.options.get("chassis")) { + (var __type, var options1) = match (router.options.get("chassis")) { /* TODO: derived ports */ None -> ("patch", map_empty()), Some{lrchassis} -> ("l3gateway", ["l3gateway-chassis" -> lrchassis]) @@ -910,8 +910,8 @@ sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), /* Create a multicast group to flood traffic and reports to router ports with * multicast flood enabled. */ -sb::Out_Multicast_Group (._uuid = hash128((rtr.lr._uuid,name)), - .datapath = rtr.lr._uuid, +sb::Out_Multicast_Group (._uuid = hash128((rtr._uuid,name)), + .datapath = rtr._uuid, .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- @@ -930,7 +930,7 @@ OutProxy_Multicast_Group (.datapath = switch.ls._uuid, /* Create a multicast group for each IGMP group learned by a Router. * 'tunnel_key' == 0 triggers an ID allocation later. */ -OutProxy_Multicast_Group (.datapath = router.lr._uuid, +OutProxy_Multicast_Group (.datapath = router._uuid, .name = address, .ports = port_ids) :- IgmpRouterMulticastGroup(address, &router, port_ids). @@ -4156,7 +4156,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .peer = Some{&RouterPort{.lrp = lrp, .is_redirect = is_redirect, - .router = &Router{.lr = lr, + .router = &Router{._uuid = lr_uuid, .redirect_port_name = redirect_port_name}}}) if (lsp.addresses.contains("router") and lsp.__type != "external")) { @@ -4194,7 +4194,7 @@ for (&SwitchPort(.lsp = lsp, /* Add ethernet addresses specified in NAT rules on * distributed logical routers. */ if (is_redirect) { - for (LogicalRouterNAT(.lr = lr._uuid, .nat = nat)) { + for (LogicalRouterNAT(.lr = lr_uuid, .nat = nat)) { if (nat.nat.__type == "dnat_and_snat") { Some{var lport} = nat.nat.logical_port in Some{var emac} = nat.nat.external_mac in @@ -4387,10 +4387,10 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam } /* Logical router ingress table ADMISSION: Admission control framework. */ -for (&Router(.lr = lr)) { +for (&Router(._uuid = lr_uuid)) { /* Logical VLANs not supported. * Broadcast/multicast source address is invalid. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ADMISSION(), .priority = 100, .__match = "vlan.present || eth.src[40]", @@ -4419,7 +4419,7 @@ for (&RouterPort(.lrp = lrp, * the pipeline. */ var actions = "${rEG_INPORT_ETH_ADDR()} = ${lrp_networks.ea}; next;" in { - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = "eth.mcast && inport == ${json_name}", @@ -4433,7 +4433,7 @@ for (&RouterPort(.lrp = lrp, * should only be received on the "redirect-chassis". */ " && is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})" } else { "" } in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = __match, @@ -4480,11 +4480,11 @@ for (&RouterPort(.lrp = lrp, * */ /* Flows for LOOKUP_NEIGHBOR. */ -for (&Router(.lr = lr, .learn_from_arp_request = learn_from_arp_request)) +for (&Router(._uuid = lr_uuid, .learn_from_arp_request = learn_from_arp_request)) var rLNR = rEGBIT_LOOKUP_NEIGHBOR_RESULT() in var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "arp.op == 2", @@ -4493,7 +4493,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in { if (learn_from_arp_request) "" else "${rLNIR} = 1; " } ++ "next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "nd_na", @@ -4502,7 +4502,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in { if (learn_from_arp_request) "" else "${rLNIR} = 1; " } ++ "next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "nd_ns", @@ -4515,7 +4515,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in /* For other packet types, we can skip neighbor learning. * So set REGBIT_LOOKUP_NEIGHBOR_RESULT to 1. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 0, .__match = "1", @@ -4524,7 +4524,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in /* Flows for LEARN_NEIGHBOR. */ /* Skip Neighbor learning if not required. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 100, .__match = @@ -4532,25 +4532,25 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in { if (learn_from_arp_request) "" else " || ${rLNIR} == 0" }, .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "arp", .actions = "put_arp(inport, arp.spa, arp.sha); next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "arp", .actions = "put_arp(inport, arp.spa, arp.sha); next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "nd_na", .actions = "put_nd(inport, nd.target, nd.tll); next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "nd_ns", @@ -4583,7 +4583,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { var actions = "${rLNR} = lookup_arp(inport, arp.spa, arp.sha); " "${rLNIR} = 1; " "next;" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 110, .__match = __match.join(" && "), @@ -4595,7 +4595,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { { if (learn_from_arp_request) "" else "${rLNIR} = lookup_arp_ip(inport, arp.spa); " } ++ "next;" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "${match0} && ${match1}", @@ -4606,11 +4606,11 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { /* Logical router ingress table IP_INPUT: IP Input. */ -for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { +for (router in &Router(._uuid = lr_uuid, .mcast_cfg = &mcast_cfg)) { /* L3 admission control: drop multicast and broadcast source, localhost * source or destination, and zero network source or destination * (priority 100). */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = "ip4.src_mcast ||" @@ -4627,7 +4627,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { * Drop IPv6 ND packets (priority 85). ND NA packets for router's own * IPs are handled with priority-90 flows. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 85, .__match = "arp || nd", @@ -4637,7 +4637,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Allow IPv6 multicast traffic that's supposed to reach the * router pipeline (e.g., router solicitations). */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 84, .__match = "nd_rs || nd_ra", @@ -4645,7 +4645,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { .external_ids = map_empty()); /* Drop other reserved multicast. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 83, .__match = "ip6.mcast_rsvd", @@ -4654,7 +4654,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Allow other multicast if relay enabled (priority 82). */ var mcast_action = { if (mcast_cfg.relay) { "next;" } else { "drop;" } } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 82, .__match = "ip4.mcast || ip6.mcast", @@ -4663,7 +4663,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Drop Ethernet local broadcast. By definition this traffic should * not be forwarded.*/ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 50, .__match = "eth.bcast", @@ -4672,7 +4672,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* TTL discard */ Flow( - .logical_datapath = lr._uuid, + .logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 30, .__match = "ip4 && ip.ttl == {0, 1}", @@ -4681,7 +4681,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Pass other traffic not already handled to the next table for * routing. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 0, .__match = "1", @@ -4768,7 +4768,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) var __match = "ip4.src == " ++ format_v4_networks(networks, true) ++ " && ${rEGBIT_EGRESS_LOOPBACK()} == 0" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = __match, @@ -4783,7 +4783,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) var __match = "ip4.dst == " ++ format_v4_networks(networks, false) ++ " && icmp4.type == 8 && icmp4.code == 0" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 90, .__match = __match, @@ -4804,7 +4804,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) * on a regular port, just reply with the port's ETH address. */ LogicalRouterNatArpNdFlow(router, nat) :- - router in &Router(.lr = nb::Logical_Router{._uuid = lr}), + router in &Router(._uuid = lr), LogicalRouterNAT(.lr = lr, .nat = nat@NAT{.nat = &nb::NAT{.__type = __type}}), /* Skip SNAT entries for now, we handle unique SNAT IPs separately * below. @@ -4831,8 +4831,8 @@ LogicalRouterArpNdFlow(router, nat, None, rEG_INPORT_ETH_ADDR(), None, false, 90 * different ETH address. */ LogicalRouterPortNatArpNdFlow(router, nat, l3dgw_port) :- - router in &Router(.lr = lr, .l3dgw_port = Some{l3dgw_port}), - LogicalRouterNAT(lr._uuid, nat), + router in &Router(._uuid = lr_uuid, .l3dgw_port = Some{l3dgw_port}), + LogicalRouterNAT(lr_uuid, nat), /* Skip SNAT entries for now, we handle unique SNAT IPs separately * below. */ @@ -4903,7 +4903,7 @@ relation LogicalRouterArpFlow( drop: bool, priority: integer, external_ids: Map) -Flow(.logical_datapath = lr.lr._uuid, +Flow(.logical_datapath = lr._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = priority, .__match = __match, @@ -4948,7 +4948,7 @@ relation LogicalRouterNdFlow( drop: bool, priority: integer, external_ids: Map) -Flow(.logical_datapath = lr.lr._uuid, +Flow(.logical_datapath = lr._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = priority, .__match = __match, @@ -4993,7 +4993,7 @@ for (RouterPortNetworksIPv4Addr(.port = &RouterPort{.lrp = lrp, .is_redirect = is_redirect}, .addr = addr)) { - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 40, .__match = "inport == ${json_name} && ip4 && " @@ -5028,7 +5028,7 @@ for (RouterPortNetworksIPv4Addr(.port = &RouterPort{.lrp = lrp, } for (&RouterPort(.lrp = lrp, - .router = router@&Router{.lr = lr}, + .router = router@&Router{._uuid = lr_uuid}, .json_name = json_name, .networks = networks, .is_redirect = is_redirect)) @@ -5036,7 +5036,7 @@ var residence_check = match (is_redirect) { true -> Some{"is_chassis_resident(${router.redirect_port_name})"}, false -> None } in { - for (RouterLBVIP(.router = &Router{.lr = nb::Logical_Router{._uuid= lr._uuid}}, .vip = vip)) { + for (RouterLBVIP(.router = &Router{._uuid= lr_uuid}, .vip = vip)) { Some{(var ip_address, _)} = ip_address_and_port_from_lb_key(vip) in { IPv4{var ipv4} = ip_address in LogicalRouterArpFlow(.lr = router, @@ -5078,7 +5078,7 @@ Flow(.logical_datapath = lr_uuid, &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, .force_lb_snat = false, - .lr = nb::Logical_Router{._uuid = lr_uuid}}, + ._uuid = lr_uuid}, .networks = networks), var addr = FlatMap(networks.ipv4_addrs), not snat_ips.contains_key(IPv4{addr.addr}), @@ -5092,7 +5092,7 @@ Flow(.logical_datapath = lr_uuid, &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, .force_lb_snat = false, - .lr = nb::Logical_Router{._uuid = lr_uuid}}, + ._uuid = lr_uuid}, .networks = networks), var addr = FlatMap(networks.ipv6_addrs), not snat_ips.contains_key(IPv6{addr.addr}), @@ -5100,7 +5100,7 @@ Flow(.logical_datapath = lr_uuid, for (RouterPortNetworksIPv4Addr( .port = &RouterPort{ - .router = &Router{.lr = lr, + .router = &Router{._uuid = lr_uuid, .l3dgw_port = None, .is_gateway = false}, .lrp = lrp}, @@ -5108,7 +5108,7 @@ for (RouterPortNetworksIPv4Addr( { /* UDP/TCP/SCTP port unreachable. */ var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && udp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5122,7 +5122,7 @@ for (RouterPortNetworksIPv4Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && tcp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5133,7 +5133,7 @@ for (RouterPortNetworksIPv4Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && sctp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5144,7 +5144,7 @@ for (RouterPortNetworksIPv4Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 70, .__match = __match, @@ -5159,7 +5159,7 @@ for (RouterPortNetworksIPv4Addr( } /* DHCPv6 reply handling */ -Flow(.logical_datapath = rp.router.lr._uuid, +Flow(.logical_datapath = rp.router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = "ip6.dst == ${ipv6_addr.addr} " @@ -5184,7 +5184,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) var __match = "ip6.dst == " ++ format_v6_networks(networks) ++ " && icmp6.type == 128 && icmp6.code == 0" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 90, .__match = __match, @@ -5227,7 +5227,7 @@ for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.lrp = lrp, /* UDP/TCP/SCTP port unreachable */ for (RouterPortNetworksIPv6Addr( - .port = &RouterPort{.router = &Router{.lr = lr, + .port = &RouterPort{.router = &Router{._uuid = lr_uuid, .l3dgw_port = None, .is_gateway = false}, .lrp = lrp, @@ -5235,7 +5235,7 @@ for (RouterPortNetworksIPv6Addr( .addr = addr)) { var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && tcp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5246,7 +5246,7 @@ for (RouterPortNetworksIPv6Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && sctp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5257,7 +5257,7 @@ for (RouterPortNetworksIPv6Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && udp" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, @@ -5271,7 +5271,7 @@ for (RouterPortNetworksIPv6Addr( .external_ids = stage_hint(lrp._uuid)); var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 70, .__match = __match, @@ -5304,7 +5304,7 @@ for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.router = &router, "icmp6.type = 3; /* Time exceeded */ " "icmp6.code = 0; /* TTL exceeded in transit */ " "next; };" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 40, .__match = __match, @@ -5322,20 +5322,20 @@ function default_allow_flow(datapath: uuid, stage: Stage): Flow { .actions = "next;", .external_ids = map_empty()} } -for (&Router(.lr = lr)) { +for (&Router(._uuid = lr_uuid)) { /* Packets are allowed by default. */ - Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_DEFRAG())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_UNSNAT())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_SNAT())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_DNAT())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_UNDNAT())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_EGR_LOOP())]; - Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_ECMP_STATEFUL())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_IN_DEFRAG())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_IN_UNSNAT())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_OUT_SNAT())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_IN_DNAT())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_OUT_UNDNAT())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_OUT_EGR_LOOP())]; + Flow[default_allow_flow(lr_uuid, s_ROUTER_IN_ECMP_STATEFUL())]; /* Send the IPv6 NS packets to next table. When ovn-controller * generates IPv6 NS (for the action - nd_ns{}), the injected * packet would go through conntrack - which is not required. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = 120, .__match = "nd_ns", @@ -5408,7 +5408,7 @@ function lrouter_nat_add_ext_ip_match( }; ("", - Some{Flow{.logical_datapath = router.lr._uuid, + Some{Flow{.logical_datapath = router._uuid, .stage = if (is_src) { s_ROUTER_IN_DNAT() } else { s_ROUTER_OUT_SNAT() }, .priority = priority, .__match = "${__match} && ${ipX}.${dir} == $${__as.name}", @@ -5446,17 +5446,17 @@ Flow(.logical_datapath = logical_router, /* Higher priority rules to force SNAT with the router port ip. * This only takes effect when the packet has already been * load balanced once. */ -for (rp in &RouterPort(.router = &Router{.lr = lr}, .lrp = lrp)) { - if (lb_force_snat_router_ip(lr.options) and rp.peer != PeerNone) { +for (rp in &RouterPort(.router = &Router{._uuid = lr_uuid, .options = lr_options}, .lrp = lrp)) { + if (lb_force_snat_router_ip(lr_options) and rp.peer != PeerNone) { Some{var ipv4} = rp.networks.ipv4_addrs.nth(0) in { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_UNSNAT(), .priority = 110, .__match = "inport == ${rp.json_name} && ip4.dst == ${ipv4.addr}", .actions = "ct_snat;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = 110, .__match = "flags.force_snat_for_lb == 1 && ip4 && outport == ${rp.json_name}", @@ -5474,14 +5474,14 @@ for (rp in &RouterPort(.router = &Router{.lr = lr}, .lrp = lrp)) { * last in the list. So add the flows only if n_ipv6_addrs > 1. */ if (rp.networks.ipv6_addrs.len() > 1) { Some{var ipv6} = rp.networks.ipv6_addrs.nth(0) in { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_UNSNAT(), .priority = 110, .__match = "inport == ${rp.json_name} && ip6.dst == ${ipv6.addr}", .actions = "ct_snat;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = 110, .__match = "flags.force_snat_for_lb == 1 && ip6 && outport == ${rp.json_name}", @@ -5501,13 +5501,13 @@ for (rp in &RouterPort(.router = &Router{.lr = lr}, .lrp = lrp)) { /* NAT rules are only valid on Gateway routers and routers with * l3dgw_port (router has a port with "redirect-chassis" * specified). */ -for (r in &Router(.lr = lr, +for (r in &Router(._uuid = lr_uuid, .l3dgw_port = l3dgw_port, .redirect_port_name = redirect_port_name, .is_gateway = is_gateway) if l3dgw_port.is_some() or is_gateway) { - for (LogicalRouterNAT(.lr = lr._uuid, .nat = nat)) { + for (LogicalRouterNAT(.lr = lr_uuid, .nat = nat)) { var ipX = nat.external_ip.ipX() in var xx = nat.external_ip.xxreg() in /* Check the validity of nat->logical_ip. 'logical_ip' can @@ -5516,7 +5516,7 @@ for (r in &Router(.lr = lr, true == match ((mask.is_all_ones(), nat.nat.__type)) { (_, "snat") -> true, (false, _) -> { - warn("bad ip ${nat.nat.logical_ip} for dnat in router ${uuid2str(lr._uuid)}"); + warn("bad ip ${nat.nat.logical_ip} for dnat in router ${uuid2str(lr_uuid)}"); false }, _ -> true @@ -5548,7 +5548,7 @@ for (r in &Router(.lr = lr, } else { "ct_snat;" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_UNSNAT(), .priority = 90, .__match = "ip && ${ipX}.dst == ${nat.nat.external_ip}", @@ -5572,7 +5572,7 @@ for (r in &Router(.lr = lr, } else { "ct_snat;" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_UNSNAT(), .priority = 100, .__match = __match, @@ -5603,7 +5603,7 @@ for (r in &Router(.lr = lr, Some{var f} = ext_flow in Flow[f]; var flag_action = - if (has_force_snat_ip(lr, "dnat")) { + if (has_force_snat_ip(r.options, "dnat")) { /* Indicate to the future tables that a DNAT has taken * place and a force SNAT needs to be done in the * Egress SNAT table. */ @@ -5615,7 +5615,7 @@ for (r in &Router(.lr = lr, "flags.loopback = 1; " "ct_dnat(${ip_and_ports});" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DNAT(), .priority = 100, .__match = __match ++ ext_ip_match, @@ -5644,7 +5644,7 @@ for (r in &Router(.lr = lr, } else { "ct_dnat(${ip_and_ports});" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DNAT(), .priority = 100, .__match = __match ++ ext_ip_match, @@ -5659,7 +5659,7 @@ for (r in &Router(.lr = lr, if (nat.nat.__type == "snat") { var __match = "inport == ${gwport_name} && " "${ipX}.src == ${nat.nat.external_ip}" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_IP_INPUT(), .priority = 120, .__match = __match, @@ -5674,7 +5674,7 @@ for (r in &Router(.lr = lr, Some{value} -> "${value}", None -> gwport.mac } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, @@ -5711,7 +5711,7 @@ for (r in &Router(.lr = lr, } else { "ct_dnat;" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_UNDNAT(), .priority = 100, .__match = __match, @@ -5746,7 +5746,7 @@ for (r in &Router(.lr = lr, "ct_snat(${ip_and_ports});" } in Some{var plen} = mask.cidr_bits() in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = plen as bit<64> + 1, .__match = __match ++ ext_ip_match, @@ -5784,7 +5784,7 @@ for (r in &Router(.lr = lr, Some{var plen} = mask.cidr_bits() in var priority = (plen as bit<64>) + 1 in var centralized_boost = if (mac == None) 128 else 0 in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = priority + centralized_boost, .__match = __match ++ ext_ip_match, @@ -5809,7 +5809,7 @@ for (r in &Router(.lr = lr, * down in the pipeline. */ var actions = "${rEG_INPORT_ETH_ADDR()} = ${gwport.mac}; next;" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = __match, @@ -5836,7 +5836,7 @@ for (r in &Router(.lr = lr, "eth.src = ${external_mac}; " "${xx}${rEG_SRC()} = ${nat.nat.external_ip}; " "next;" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 100, .__match = __match, @@ -5872,7 +5872,7 @@ for (r in &Router(.lr = lr, regs.join("") ++ "${rEGBIT_EGRESS_LOOPBACK()} = 1; " "next(pipeline=ingress, table=0); };" in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_EGR_LOOP(), .priority = 100, .__match = __match, @@ -5883,15 +5883,15 @@ for (r in &Router(.lr = lr, /* Handle force SNAT options set in the gateway router. */ if (l3dgw_port == None) { - var dnat_force_snat_ips = get_force_snat_ip(lr, "dnat") in + var dnat_force_snat_ips = get_force_snat_ip(r.options, "dnat") in if (not dnat_force_snat_ips.is_empty()) - LogicalRouterForceSnatFlows(.logical_router = lr._uuid, + LogicalRouterForceSnatFlows(.logical_router = lr_uuid, .ips = dnat_force_snat_ips, .context = "dnat"); - var lb_force_snat_ips = get_force_snat_ip(lr, "lb") in + var lb_force_snat_ips = get_force_snat_ip(r.options, "lb") in if (not lb_force_snat_ips.is_empty()) - LogicalRouterForceSnatFlows(.logical_router = lr._uuid, + LogicalRouterForceSnatFlows(.logical_router = lr_uuid, .ips = lb_force_snat_ips, .context = "lb"); @@ -5904,7 +5904,7 @@ for (r in &Router(.lr = lr, * does not have any feature that depends on the source * ip address being external IP address for IP routing, * we can do it here, saving a future re-circulation. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DNAT(), .priority = 50, .__match = "ip", @@ -5925,11 +5925,11 @@ function nats_contain_vip(nats: Vec, vip: v46_ip): bool { /* Load balancing and packet defrag are only valid on * Gateway routers or router with gateway port. */ for (RouterLBVIP( - .router = &Router{.lr = lr, - .l3dgw_port = l3dgw_port, - .redirect_port_name = redirect_port_name, - .is_gateway = is_gateway, - .nats = nats}, + .router = r@&Router{._uuid = lr_uuid, + .l3dgw_port = l3dgw_port, + .redirect_port_name = redirect_port_name, + .is_gateway = is_gateway, + .nats = nats}, .lb = lb, .vip = vip, .backends = backends) @@ -5940,7 +5940,7 @@ for (RouterLBVIP( for (HasEventElbMeter(has_elb_meter)) { Some {(var __match, var __action)} = build_empty_lb_event_flow(vip, lb, has_elb_meter) in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DNAT(), .priority = 130, .__match = __match, @@ -5972,7 +5972,7 @@ for (RouterLBVIP( * We create one for each VIP:port pair; flows with the same IP and * different port numbers will produce identical flows that will * get merged by DDlog. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DEFRAG(), .priority = 100, .__match = __match, @@ -5996,7 +5996,7 @@ for (RouterLBVIP( (Some{gwport}, true) -> " && is_chassis_resident(${redirect_port_name})", _ -> "" } in - var snat_for_lb = snat_for_lb(lr, lb) in + var snat_for_lb = snat_for_lb(r.options, lb) in { /* A match and actions for established connections. */ var est_match = "ct.est && " ++ __match in @@ -6006,7 +6006,7 @@ for (RouterLBVIP( ForceSNAT -> "flags.force_snat_for_lb = 1; ct_dnat;", _ -> "ct_dnat;" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_DNAT(), .priority = prio, .__match = est_match, @@ -6028,7 +6028,7 @@ for (RouterLBVIP( var match3 = "${ipX} && ${ipX}.dst == ${ip_address} && ${proto}" ++ if (port != 0) { " && ${proto}.dst == ${port}" } else { "" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_UNSNAT(), .priority = 120, .__match = match3, @@ -6068,7 +6068,7 @@ for (RouterLBVIP( ForceSNAT -> "flags.force_snat_for_lb = 1; ct_dnat;", _ -> "ct_dnat;" } in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_UNDNAT(), .priority = 120, .__match = undnat_match, @@ -6083,7 +6083,7 @@ for (RouterLBVIP( * via add_router_lb_flow(). One flow is for specific matching * on ct.new with an action of "ct_lb($targets);". The other * flow is for ct.est with an action of "ct_dnat;". */ -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_DNAT(), .priority = priority, .__match = __match, @@ -6092,7 +6092,7 @@ Flow(.logical_datapath = r.lr._uuid, r in &Router(), r.l3dgw_port.is_some() or r.is_gateway, LBVIPWithStatus[lbvip@&LBVIPWithStatus{.lb = lb}], - r.lr.load_balancer.contains(lb._uuid), + r.load_balancer.contains(lb._uuid), var __match = "ct.new && " ++ get_match_for_lb_key(lbvip.vip_addr, lbvip.vip_port, lb.protocol, true) ++ @@ -6101,7 +6101,7 @@ Flow(.logical_datapath = r.lr._uuid, _ -> "" }, var priority = if (lbvip.vip_port != 0) 120 else 110, - var force_snat = match (snat_for_lb(r.lr, lb)) { + var force_snat = match (snat_for_lb(r.options, lb)) { SkipSNAT -> "flags.skip_snat_for_lb = 1; ", ForceSNAT -> "flags.force_snat_for_lb = 1; ", _ -> "" @@ -6247,7 +6247,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None Some{prf} -> ", router_preference = \"${prf}\"" } in var actions = actions0 ++ router_preference ++ prefix ++ "); next;" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ND_RA_OPTIONS(), .priority = 50, .__match = __match, @@ -6261,7 +6261,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None "ip6.dst = ip6.src; ip6.src = ${ip6_str}; " "outport = inport; flags.loopback = 1; " "output;" in - Flow(.logical_datapath = router.lr._uuid, + Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ND_RA_RESPONSE(), .priority = 50, .__match = __match, @@ -6274,15 +6274,15 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None /* Logical router ingress table ND_RA_OPTIONS, ND_RA_RESPONSE: RS responder, by * default goto next. (priority 0)*/ -for (&Router(.lr = lr)) +for (&Router(._uuid = lr_uuid)) { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ND_RA_OPTIONS(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ND_RA_RESPONSE(), .priority = 0, .__match = "1", @@ -6344,7 +6344,7 @@ for (Route(.port = port, "flags.loopback = 1; " "next;" in { - Flow(.logical_datapath = port.router.lr._uuid, + Flow(.logical_datapath = port.router._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = priority as integer, .__match = __match, @@ -6352,7 +6352,7 @@ for (Route(.port = port, .external_ids = stage_hint(port.lrp._uuid)); if (port.has_bfd) { - Flow(.logical_datapath = port.router.lr._uuid, + Flow(.logical_datapath = port.router._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = priority as integer + 1, .__match = "${__match} && udp.dst == 3784", @@ -6387,7 +6387,7 @@ Route(key, port, src_ip, None) :- var key = RouteKey{DstIp, IPv6{addr.addr}, addr.plen}, var src_ip = IPv6{addr.addr}. -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_IP_ROUTING_ECMP(), .priority = 150, .__match = "${rEG_ECMP_GROUP_ID()} == 0", @@ -6429,7 +6429,7 @@ EcmpGroup(group_id, router, key, dsts, route_match, route_priority) :- (var route_match, var route_priority0) = build_route_match(key), var route_priority = route_priority0 as integer. -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = route_priority, .__match = route_match, @@ -6449,7 +6449,7 @@ Flow(.logical_datapath = router.lr._uuid, "${rEG_ECMP_GROUP_ID()} = ${group_id}; " /* XXX */ "${rEG_ECMP_MEMBER_ID()} = select(${all_member_ids});". -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_ROUTING_ECMP(), .priority = 100, .__match = __match, @@ -6482,7 +6482,7 @@ EcmpSymmetricReply(router, dst, route_match, tunkey) :- dst.ecmp_symmetric_reply, PortTunKeyAllocation(.port = dst.port.lrp._uuid, .tunkey = tunkey). -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_DEFRAG(), .priority = 100, .__match = __match, @@ -6497,7 +6497,7 @@ Flow(.logical_datapath = router.lr._uuid, /* Save src eth and inport in ct_label for packets that arrive over * an ECMP route. */ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ECMP_STATEFUL(), .priority = 100, .__match = __match, @@ -6512,7 +6512,7 @@ Flow(.logical_datapath = router.lr._uuid, /* Bypass ECMP selection if we already have ct_label information * for where to route the packet. */ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 100, .__match = "${ecmp_reply} && ${route_match}", @@ -6524,13 +6524,13 @@ Flow(.logical_datapath = router.lr._uuid, "next;", .external_ids = map_empty()), /* Egress reply traffic for symmetric ECMP routes skips router policies. */ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_POLICY(), .priority = 65535, .__match = ecmp_reply, .actions = "next;", .external_ids = map_empty()), -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 200, .__match = ecmp_reply, @@ -6547,7 +6547,7 @@ Flow(.logical_datapath = router.lr._uuid, /* Drop IPv6 multicast traffic that shouldn't be forwarded, * i.e., router solicitation and router advertisement. */ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 550, .__match = "nd_rs || nd_ra", @@ -6572,7 +6572,7 @@ for (IgmpRouterMulticastGroup(address, &rtr, ports)) { } in Some{var ip} = ip46_parse(address) in var ipX = ip.ipX() in - UniqueFlow[Flow{.logical_datapath = rtr.lr._uuid, + UniqueFlow[Flow{.logical_datapath = rtr._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 500, .__match = "${ipX} && ${ipX}.dst == ${address} ", @@ -6598,7 +6598,7 @@ for (RouterMcastFloodPorts(&rtr, flood_ports) if rtr.mcast_cfg.relay) { } else { "drop;" } in - AnnotatedFlow(.f = Flow{.logical_datapath = rtr.lr._uuid, + AnnotatedFlow(.f = Flow{.logical_datapath = rtr._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 450, .__match = "ip4.mcast || ip6.mcast", @@ -6616,17 +6616,17 @@ for (RouterMcastFloodPorts(&rtr, flood_ports) if rtr.mcast_cfg.relay) { * the appropriate register to the next-hop IP address (leaving * 'ip[46].dst', the packet’s final destination, unchanged), and * advances to the next table for ARP/ND resolution. */ -for (&Router(.lr = lr)) { +for (&Router(._uuid = lr_uuid)) { /* This is a catch-all rule. It has the lowest priority (0) * does a match-all("1") and pass-through (next) */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_POLICY(), .priority = 0, .__match = "1", .actions = "${rEG_ECMP_GROUP_ID()} = 0; next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_POLICY_ECMP(), .priority = 150, .__match = "${rEG_ECMP_GROUP_ID()} == 0", @@ -6648,14 +6648,14 @@ function pkt_mark_policy(options: Map): string { "" } } -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = actions, .external_ids = stage_hint(policy._uuid)) :- r in &Router(), - var policy_uuid = FlatMap(r.lr.policies), + var policy_uuid = FlatMap(r.policies), policy in nb::Logical_Router_Policy(._uuid = policy_uuid), policy.action == "reroute", Some{var nexthop_s} = match (policy.nexthops.size()) { @@ -6699,7 +6699,7 @@ relation EcmpReroutePolicy( ) EcmpReroutePolicy(r, policy, ecmp_group_id) :- r in &Router(), - var policy_uuid = FlatMap(r.lr.policies), + var policy_uuid = FlatMap(r.policies), policy in nb::Logical_Router_Policy(._uuid = policy_uuid), policy.action == "reroute", policy.nexthops.size() > 1, @@ -6709,7 +6709,7 @@ EcmpReroutePolicy(r, policy, ecmp_group_id) :- var pair = FlatMap(numbered_policies), (var policy, var ecmp_group_id) = pair, all_same_addr_family(policy.nexthops). -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_POLICY_ECMP(), .priority = 100, .__match = __match, @@ -6733,7 +6733,7 @@ Flow(.logical_datapath = r.lr._uuid, "next;"), var __match = ("${rEG_ECMP_GROUP_ID()} == ${ecmp_group_id} && " "${rEG_ECMP_MEMBER_ID()} == ${member_id}"). -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, @@ -6750,25 +6750,25 @@ Flow(.logical_datapath = r.lr._uuid, }, var actions = ("${rEG_ECMP_GROUP_ID()} = ${ecmp_group_id}; " "${rEG_ECMP_MEMBER_ID()} = select(${member_ids});"). - -Flow(.logical_datapath = r.lr._uuid, + +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = "drop;", .external_ids = stage_hint(policy._uuid)) :- r in &Router(), - var policy_uuid = FlatMap(r.lr.policies), + var policy_uuid = FlatMap(r.policies), policy in nb::Logical_Router_Policy(._uuid = policy_uuid), policy.action == "drop". -Flow(.logical_datapath = r.lr._uuid, +Flow(.logical_datapath = r._uuid, .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = pkt_mark_policy(policy.options) ++ "${rEG_ECMP_GROUP_ID()} = 0; next;", .external_ids = stage_hint(policy._uuid)) :- r in &Router(), - var policy_uuid = FlatMap(r.lr.policies), + var policy_uuid = FlatMap(r.policies), policy in nb::Logical_Router_Policy(._uuid = policy_uuid), policy.action == "allow". @@ -6780,8 +6780,8 @@ Flow(.logical_datapath = r.lr._uuid, * Multicast packets already have the outport set so just advance to next * table (priority 500). */ -for (&Router(.lr = lr)) { - Flow(.logical_datapath = lr._uuid, +for (&Router(._uuid = lr_uuid)) { + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 500, .__match = "ip4.mcast || ip6.mcast", @@ -6816,7 +6816,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, var __match = "outport == ${peer_json_name} && " "${rEG_NEXT_HOP()} == " ++ format_v4_networks(networks, false) in - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, @@ -6828,7 +6828,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, var __match = "outport == ${peer_json_name} && " "xx${rEG_NEXT_HOP()} == " ++ format_v6_networks(networks) in - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, @@ -6844,7 +6844,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, * is "bridged", instead of calling "get_arp" * on this node, we will redirect the packet to gateway * chassis, by setting destination mac router port mac.*/ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 50, .__match = "outport == ${rp.json_name} && " @@ -6870,7 +6870,7 @@ Flow(.logical_datapath = lr_uuid, .external_ids = stage_hint(lrp_uuid)) :- &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, - .lr = nb::Logical_Router{._uuid = lr_uuid}}, + ._uuid = lr_uuid}, .networks = networks), var addr = FlatMap(networks.ipv4_addrs), snat_ips.contains_key(IPv4{addr.addr}), @@ -6883,7 +6883,7 @@ Flow(.logical_datapath = lr_uuid, .external_ids = stage_hint(lrp_uuid)) :- &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, - .lr = nb::Logical_Router{._uuid = lr_uuid}}, + ._uuid = lr_uuid}, .networks = networks), var addr = FlatMap(networks.ipv6_addrs), snat_ips.contains_key(IPv6{addr.addr}), @@ -6904,7 +6904,7 @@ for (SwitchPortIPv4Address( .peer = Some{&peer@RouterPort{.router = &peer_router}})) { Some{_} = find_lrp_member_ip(peer.networks, IPv4{addr.addr}) in - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " @@ -6924,7 +6924,7 @@ for (SwitchPortIPv6Address( .peer = Some{&peer@RouterPort{.router = &peer_router}})) { Some{_} = find_lrp_member_ip(peer.networks, IPv6{addr.addr}) in - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " @@ -6954,7 +6954,7 @@ function is_empty_set_or_string(s: Option): bool = { * 00:00:00:00:00:00 and advance to next table so that ARP is * resolved by router pipeline using the arp{} action. * The MAC_Binding entry for the virtual ip might be invalid. */ -Flow(.logical_datapath = peer.router.lr._uuid, +Flow(.logical_datapath = peer.router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " @@ -6969,7 +6969,7 @@ Flow(.logical_datapath = peer.router.lr._uuid, is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None, sp2 in &SwitchPort(.sw = sp.sw, .peer = Some{peer}), Some{_} = find_lrp_member_ip(peer.networks, IPv4{virtual_ip}). -Flow(.logical_datapath = peer.router.lr._uuid, +Flow(.logical_datapath = peer.router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " @@ -6998,7 +6998,7 @@ for (&SwitchPort(.lsp = lsp1, .peer = Some{&peer1@RouterPort{.router = &peer_router}}, .sw = &sw) if lsp1.is_enabled() and - not peer_router.lr.options.get_bool_def("dynamic_neigh_routers", false)) + not peer_router.options.get_bool_def("dynamic_neigh_routers", false)) { for (&SwitchPort(.lsp = lsp2, .peer = Some{&peer2}, .sw = &Switch{.ls = nb::Logical_Switch{._uuid = sw.ls._uuid}}) @@ -7006,7 +7006,7 @@ for (&SwitchPort(.lsp = lsp1, if peer2.lrp._uuid != peer1.lrp._uuid) { if (not peer2.networks.ipv4_addrs.is_empty()) { - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer1.json_name} && " @@ -7016,7 +7016,7 @@ for (&SwitchPort(.lsp = lsp1, }; if (not peer2.networks.ipv6_addrs.is_empty()) { - Flow(.logical_datapath = peer_router.lr._uuid, + Flow(.logical_datapath = peer_router._uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer1.json_name} && " @@ -7027,15 +7027,15 @@ for (&SwitchPort(.lsp = lsp1, } } -for (&Router(.lr = lr)) +for (&Router(._uuid = lr_uuid)) { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 0, .__match = "ip4", .actions = "get_arp(outport, ${rEG_NEXT_HOP()}); next;", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 0, .__match = "ip6", @@ -7056,35 +7056,35 @@ for (&Router(.lr = lr)) * generate ICMPv4 packet with type 3 (Destination Unreachable) and * code 4 (Fragmentation needed). * */ -Flow(.logical_datapath = lr._uuid, +Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_CHK_PKT_LEN(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- - &Router(.lr = lr). -Flow(.logical_datapath = lr._uuid, + &Router(._uuid = lr_uuid). +Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- - &Router(.lr = lr). -Flow(.logical_datapath = lr._uuid, + &Router(._uuid = lr_uuid). +Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_CHK_PKT_LEN(), .priority = 50, .__match = "outport == ${l3dgw_port_json_name}", .actions = "${rEGBIT_PKT_LARGER()} = check_pkt_larger(${mtu}); " "next;", .external_ids = stage_hint(l3dgw_port._uuid)) :- - r in &Router(.lr = lr), + r in &Router(._uuid = lr_uuid), Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), gw_mtu > 0, var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(). -Flow(.logical_datapath = lr._uuid, +Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 50, .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " @@ -7102,7 +7102,7 @@ Flow(.logical_datapath = lr._uuid, "next(pipeline=ingress, table=0); " "};", .external_ids = stage_hint(rp.lrp._uuid)) :- - r in &Router(.lr = lr), + r in &Router(._uuid = lr_uuid), Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", @@ -7111,7 +7111,7 @@ Flow(.logical_datapath = lr._uuid, rp in &RouterPort(.router = r), rp.lrp != l3dgw_port, Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). -Flow(.logical_datapath = lr._uuid, +Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 50, .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " @@ -7129,7 +7129,7 @@ Flow(.logical_datapath = lr._uuid, "next(pipeline=ingress, table=0); " "};", .external_ids = stage_hint(rp.lrp._uuid)) :- - r in &Router(.lr = lr), + r in &Router(._uuid = lr_uuid), Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", @@ -7146,7 +7146,7 @@ Flow(.logical_datapath = lr._uuid, * of the traffic to the l3redirect_port which represents * the central instance of the l3dgw_port. */ -for (&Router(.lr = lr, +for (&Router(._uuid = lr_uuid, .l3dgw_port = l3dgw_port, .redirect_port_name = redirect_port_name)) { @@ -7155,7 +7155,7 @@ for (&Router(.lr = lr, * rule, then the traffic is redirected to the central * instance of the l3dgw_port. */ Some{var gwport} = l3dgw_port in - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 50, .__match = "outport == ${json_string_escape(gwport.name)}", @@ -7163,7 +7163,7 @@ for (&Router(.lr = lr, .external_ids = stage_hint(gwport._uuid)); /* Packets are allowed by default. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 0, .__match = "1", @@ -7176,7 +7176,7 @@ for (&Router(.lr = lr, * In the common case where the Ethernet destination has been resolved, * this table outputs the packet (priority 0). Otherwise, it composes * and sends an ARP/IPv6 NA request (priority 100). */ -Flow(.logical_datapath = router.lr._uuid, +Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 200, .__match = __match, @@ -7197,9 +7197,9 @@ Flow(.logical_datapath = router.lr._uuid, "output; " "};". -for (&Router(.lr = lr)) +for (&Router(._uuid = lr_uuid)) { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 100, .__match = "eth.dst == 00:00:00:00:00:00 && ip4", @@ -7212,7 +7212,7 @@ for (&Router(.lr = lr)) "};", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 100, .__match = "eth.dst == 00:00:00:00:00:00 && ip6", @@ -7222,7 +7222,7 @@ for (&Router(.lr = lr)) "};", .external_ids = map_empty()); - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 0, .__match = "1", @@ -7237,7 +7237,7 @@ for (&Router(.lr = lr)) for (&RouterPort(.lrp = lrp, .json_name = json_name, .networks = lrp_networks, - .router = &Router{.lr = lr, .mcast_cfg = &mcast_cfg}) + .router = &Router{._uuid = lr_uuid, .mcast_cfg = &mcast_cfg}) /* Drop packets to disabled logical ports (since logical flow * tables are default-drop). */ if lrp.is_enabled()) @@ -7246,7 +7246,7 @@ for (&RouterPort(.lrp = lrp, * multicast traffic. */ if (mcast_cfg.relay) { - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_DELIVERY(), .priority = 110, .__match = "(ip4.mcast || ip6.mcast) && " @@ -7259,7 +7259,7 @@ for (&RouterPort(.lrp = lrp, * be replaced by the l3dgw port in the local output * pipeline stage before egress processing. */ - Flow(.logical_datapath = lr._uuid, + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_OUT_DELIVERY(), .priority = 100, .__match = "outport == ${json_name}", @@ -7405,7 +7405,7 @@ RequestedPortTunKey(datapath, port, tunkey) :- Some{var tunkey} = get_port_tunkey(sp.lsp.options, "requested-tnl-key"). RequestedPortTunKey(datapath, port, tunkey) :- rp in &RouterPort(), - var datapath = rp.router.lr._uuid, + var datapath = rp.router._uuid, var port = rp.lrp._uuid, Some{var tunkey} = get_port_tunkey(rp.lrp.options, "requested-tnl-key"). Warning[message] :- @@ -7909,7 +7909,7 @@ function lrouter_bfd_flows(lr_uuid: uuid, lrp_uuid: uuid, ipX: string, networks: } for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp, .has_bfd = true)) { if (not networks.ipv4_addrs.is_empty()) { - (var a, var b) = lrouter_bfd_flows(router.lr._uuid, lrp._uuid, "ip4", + (var a, var b) = lrouter_bfd_flows(router._uuid, lrp._uuid, "ip4", format_v4_networks(networks, false)) in { Flow[a]; Flow[b] @@ -7917,14 +7917,14 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp, .has_bfd = }; if (not networks.ipv6_addrs.is_empty()) { - (var a, var b) = lrouter_bfd_flows(router.lr._uuid, lrp._uuid, "ip6", + (var a, var b) = lrouter_bfd_flows(router._uuid, lrp._uuid, "ip6", format_v6_networks(networks)) in { Flow[a]; Flow[b] } } -} - +} + /* Clean up stale FDB entries. */ sb::Out_FDB(_uuid, mac, dp_key, port_key) :- sb::FDB(_uuid, mac, dp_key, port_key), From patchwork Fri May 7 04:06:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475329 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxlS6gBmz9sPf for ; Fri, 7 May 2021 14:08:52 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 7C126844FC; Fri, 7 May 2021 04:08:50 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ouZtZZ_tyijj; Fri, 7 May 2021 04:08:47 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTP id 9F37E84451; Fri, 7 May 2021 04:08:15 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 90509C0022; Fri, 7 May 2021 04:08:14 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 17979C0001 for ; Fri, 7 May 2021 04:08:13 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A6FD283CC5 for ; Fri, 7 May 2021 04:07:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ELCuZBVKaTzk for ; Fri, 7 May 2021 04:07:31 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id C8F2C8275A for ; Fri, 7 May 2021 04:07:30 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 15548C0006; Fri, 7 May 2021 04:07:27 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:46 -0700 Message-Id: <20210507040659.26830-15-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 14/27] ovn-northd-ddlog: Intern the `Router` table. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk This is the first in a series of commits that will replace the use of the DDlog's `Ref<>` type with `Intern<>` throughout the OVN code base. `Ref` and `Intern` are the two forms of smart pointers supported by DDlog at the moment. `Ref` is a reference counted pointer. Copying a `Ref<>` simply increments its reference count. `Intern<>` is an interned object reference. It guarantees that there exists exactly one copy of each unique interned value. Interned objects are slightly more expensive to create, but they have several important advantages: (1) they save memory by deduplicating identical values, (2) they allow by-pointer comparisons, and (3) they avoid unnecessary recomputations in some scenarios. See DDlog docs [1], [2] for more detail. In this commit we change the type of records in the `Router` table from `Ref` to `Intern`. This reduces the amount of churn and speeds up northd significantly in scenarios where the set of router ports changes frequently, which triggers updates to `nb::Logical_Router`, which in turn updates corresponding records in the `Router` table. Interning guarantees that these updates are no-ops and do not trigger any other rules. [1] https://github.com/vmware/differential-datalog/blob/master/doc/tutorial/tutorial.md#reference-type-ref [2] https://github.com/vmware/differential-datalog/blob/master/doc/tutorial/tutorial.md#interned-values-intern-istring Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 21 ++++++++++++--------- northd/multicast.dl | 6 +++--- northd/ovn_northd.dl | 31 +++++++++++++++---------------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 07579fb45902..87550c4fcb36 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -440,7 +440,7 @@ LogicalRouterLBs(lr, vec_empty()) :- function chassis_redirect_name(port_name: string): string = "cr-${port_name}" -relation &Router( +typedef Router = Router { /* Fields copied from nb::Logical_Router. */ _uuid: uuid, name: string, @@ -462,9 +462,12 @@ relation &Router( mcast_cfg: Ref, learn_from_arp_request: bool, force_lb_snat: bool, -) +} + +relation Router[Intern] -&Router(._uuid = lr._uuid, +Router[Router{ + ._uuid = lr._uuid, .name = lr.name, .static_routes = lr.static_routes, .policies = lr.policies, @@ -486,7 +489,7 @@ relation &Router( .lbs = lbs, .mcast_cfg = mcast_cfg, .learn_from_arp_request = learn_from_arp_request, - .force_lb_snat = force_lb_snat) :- + .force_lb_snat = force_lb_snat}.intern()] :- lr in nb::Logical_Router(), lr.is_enabled(), LogicalRouterRedirectPort(lr._uuid, l3dgw_port), @@ -498,7 +501,7 @@ relation &Router( var force_lb_snat = lb_force_snat_router_ip(lr.options). /* RouterLB: many-to-many relation between logical routers and nb::LB */ -relation RouterLB(router: Ref, lb: Ref) +relation RouterLB(router: Intern, lb: Ref) RouterLB(router, lb) :- router in &Router(.lbs = lbs), @@ -506,7 +509,7 @@ RouterLB(router, lb) :- /* Load balancer VIPs associated with routers */ relation RouterLBVIP( - router: Ref, + router: Intern, lb: Ref, vip: string, backends: string) @@ -586,7 +589,7 @@ relation &RouterPort( lrp: nb::Logical_Router_Port, json_name: string, networks: lport_addresses, - router: Ref, + router: Intern, is_redirect: bool, peer: RouterPeer, mcast_cfg: Ref, @@ -721,7 +724,7 @@ function find_lrp_member_ip(networks: lport_addresses, ip: v46_ip): Option, + router : Intern, key : route_key, nexthop : v46_ip, output_port : Option, @@ -745,7 +748,7 @@ typedef route_dst = RouteDst { } relation RouterStaticRoute( - router : Ref, + router : Intern, key : route_key, dsts : Set) diff --git a/northd/multicast.dl b/northd/multicast.dl index 990203bffe25..9b0fa80738d7 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -160,7 +160,7 @@ SwitchMcastFloodReportPorts(switch, set_empty()) :- /* Mapping between Router and the set of port uuids on which to * flood IP multicast reports statically. */ -relation RouterMcastFloodPorts(sw: Ref, ports: Set) +relation RouterMcastFloodPorts(sw: Intern, ports: Set) RouterMcastFloodPorts(router, flood_ports) :- &RouterPort( @@ -213,7 +213,7 @@ IgmpSwitchMulticastGroup(address, switch, ports) :- */ relation IgmpRouterGroupPort( address: string, - router : Ref, + router : Intern, port : uuid ) @@ -236,7 +236,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :- */ relation IgmpRouterMulticastGroup( address: string, - router : Ref, + router : Intern, ports : Set ) diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index fad633b1870e..51bbc832b7b6 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -297,7 +297,7 @@ OutProxy_Port_Binding(._uuid = lrp._uuid, }. /* */ -function get_router_load_balancer_ips(router: Router) : +function get_router_load_balancer_ips(router: Intern) : (Set, Set) = { var all_ips_v4 = set_empty(); @@ -327,8 +327,7 @@ function get_router_load_balancer_ips(router: Router) : function get_nat_addresses(rport: RouterPort): Set = { var addresses = set_empty(); - var router = deref(rport.router); - var has_redirect = router.l3dgw_port.is_some(); + var has_redirect = rport.router.l3dgw_port.is_some(); match (eth_addr_from_string(rport.lrp.mac)) { None -> addresses, Some{mac} -> { @@ -336,7 +335,7 @@ function get_nat_addresses(rport: RouterPort): Set = var central_ip_address = false; /* Get NAT IP addresses. */ - for (nat in router.nats) { + for (nat in rport.router.nats) { /* Determine whether this NAT rule satisfies the conditions for * distributed NAT processing. */ if (has_redirect and nat.nat.__type == "dnat_and_snat" and @@ -379,7 +378,7 @@ function get_nat_addresses(rport: RouterPort): Set = }; /* A set to hold all load-balancer vips. */ - (var all_ips_v4, var all_ips_v6) = get_router_load_balancer_ips(router); + (var all_ips_v4, var all_ips_v6) = get_router_load_balancer_ips(rport.router); for (ip_address in set_union(all_ips_v4, all_ips_v6)) { c_addresses = c_addresses ++ " ${ip_address}"; @@ -390,7 +389,7 @@ function get_nat_addresses(rport: RouterPort): Set = /* Gratuitous ARP for centralized NAT rules on distributed gateway * ports should be restricted to the gateway chassis. */ if (has_redirect) { - c_addresses = c_addresses ++ " is_chassis_resident(${router.redirect_port_name})" + c_addresses = c_addresses ++ " is_chassis_resident(${rport.router.redirect_port_name})" } else (); addresses.insert(c_addresses) @@ -4048,7 +4047,7 @@ function get_arp_forward_ips(rp: Ref): (Set, Set) = var all_ips_v6 = set_empty(); (var lb_ips_v4, var lb_ips_v6) - = get_router_load_balancer_ips(deref(rp.router)); + = get_router_load_balancer_ips(rp.router); for (a in lb_ips_v4) { /* Check if the ovn port has a network configured on which we could * expect ARP requests for the LB VIP. @@ -4817,7 +4816,7 @@ LogicalRouterNatArpNdFlow(router, nat) :- (var ip, var nats) = snat_ip, Some{var nat} = nats.nth(0). -relation LogicalRouterNatArpNdFlow(router: Ref, nat: NAT) +relation LogicalRouterNatArpNdFlow(router: Intern, nat: NAT) LogicalRouterArpNdFlow(router, nat, None, rEG_INPORT_ETH_ADDR(), None, false, 90) :- LogicalRouterNatArpNdFlow(router, nat). @@ -4847,7 +4846,7 @@ LogicalRouterPortNatArpNdFlow(router, nat, l3dgw_port) :- /* Respond to ARP/NS requests on the chassis that binds the gw * port. Drop the ARP/NS requests on other chassis. */ -relation LogicalRouterPortNatArpNdFlow(router: Ref, nat: NAT, lrp: nb::Logical_Router_Port) +relation LogicalRouterPortNatArpNdFlow(router: Intern, nat: NAT, lrp: nb::Logical_Router_Port) LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, Some{extra_match}, false, 92), LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :- LogicalRouterPortNatArpNdFlow(router, nat, lrp), @@ -4878,7 +4877,7 @@ LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :- /* Now divide the ARP/ND flows into ARP and ND. */ relation LogicalRouterArpNdFlow( - router: Ref, + router: Intern, nat: NAT, lrp: Option, mac: string, @@ -4895,7 +4894,7 @@ LogicalRouterNdFlow(router, lrp, "nd_na", ipv6, true, mac, extra_match, drop, pr mac, extra_match, drop, priority). relation LogicalRouterArpFlow( - lr: Ref, + lr: Intern, lrp: Option, ip: in_addr, mac: string, @@ -4938,7 +4937,7 @@ Flow(.logical_datapath = lr._uuid, }. relation LogicalRouterNdFlow( - lr: Ref, + lr: Intern, lrp: Option, action: string, ip: in6_addr, @@ -5368,7 +5367,7 @@ function lrouter_nat_is_stateless(nat: NAT): bool = { * and action says "next" instead of ct*. */ function lrouter_nat_add_ext_ip_match( - router: Ref, + router: Intern, nat: NAT, __match: string, ipX: string, @@ -6414,7 +6413,7 @@ function numbered_vec(set: Set<'A>) : Vec<(bit<16>, 'A)> = { relation EcmpGroup( group_id: bit<16>, - router: Ref, + router: Intern, key: route_key, dsts: Set, route_match: string, // This is build_route_match(key).0 @@ -6471,7 +6470,7 @@ Flow(.logical_datapath = router._uuid, * an ECMP route need to go through conntrack. */ relation EcmpSymmetricReply( - router: Ref, + router: Intern, dst: route_dst, route_match: string, tunkey: integer) @@ -6693,7 +6692,7 @@ function all_same_addr_family(addrs: Set): bool { } relation EcmpReroutePolicy( - r: Ref, + r: Intern, policy: nb::Logical_Router_Policy, ecmp_group_id: usize ) From patchwork Fri May 7 04:06:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475328 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxlN3rbZz9sPf for ; Fri, 7 May 2021 14:08:48 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id EF453844D5; Fri, 7 May 2021 04:08:46 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7zXGl-kASbS2; Fri, 7 May 2021 04:08:44 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id CF55684439; Fri, 7 May 2021 04:08:12 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id A8077C000E; Fri, 7 May 2021 04:08:12 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 19F90C0001 for ; Fri, 7 May 2021 04:08:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 6338183DB9 for ; Fri, 7 May 2021 04:07:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id i5ZQDDBEtbRX for ; Fri, 7 May 2021 04:07:33 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 99A7D83CC5 for ; Fri, 7 May 2021 04:07:32 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id C32E5C0009; Fri, 7 May 2021 04:07:29 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:47 -0700 Message-Id: <20210507040659.26830-16-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 15/27] ovn-northd-ddlog: Workaround for slow group_by. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk This patch is a workaround for a performance issue in the DDlog compiler. The issue will hopefully be resolved in a future version of DDlog, but for now we need this and possibly a few other similar fixes. Here is one affected rule: ``` sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_names) :- nb::Port_Group(._uuid = _uuid, .name = nb_name, .ports = pg_ports), var port_uuid = FlatMap(pg_ports), &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{._uuid = port_uuid, .name = port_name}, .sw = &Switch{.ls = nb::Logical_Switch{._uuid = ls_uuid}}), TunKeyAllocation(.datapath = ls_uuid, .tunkey = tunkey), var sb_name = "${tunkey}_${nb_name}", var port_names = port_name.group_by((_uuid, sb_name)).to_set(). ``` The first literal in the body of the rule binds variable `pg_ports` to the array of ports in the port group. This is a potentially large array that immediately gets flattened by the `FlatMap` operator. Since the `pg_ports` variable is not used in the remainder of the rule, DDlog normally would not propagate it through the rest of the rule. Unfortunately, due to a subtle semantic quirk, the behavior is different when there is a `group_by` operator further down in the rule, in which case unused variables are still propagated through the rule, which involves expensive copies. The workaround I implemented factors the first two terms in the rule into a separate `PortGroupPort` relation, so that the ports array no longer occurs in the new version of the rule: ``` sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_names) :- PortGroupPort(.pg_uuid = _uuid, .pg_name = nb_name, .port = port_uuid), &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{._uuid = port_uuid, .name = port_name}, .sw = &Switch{.ls = nb::Logical_Switch{._uuid = ls_uuid}}), TunKeyAllocation(.datapath = ls_uuid, .tunkey = tunkey), var sb_name = "${tunkey}_${nb_name}", var port_names = port_name.group_by((_uuid, sb_name)).to_set(). ``` Again, benchmarking is likely to reveal more instances of this. A proper fix will require a change to the DDlog compiler. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/ovn_northd.dl | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 51bbc832b7b6..50203de88867 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -720,11 +720,10 @@ sb::Out_Address_Set(._uuid = hash128("svc_monitor_mac"), SvcMonitorMac(svc_monitor_mac). sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :- - nb::Port_Group(.ports = pg_ports, .name = pg_name), + PortGroupPort(.pg_name = pg_name, .port = port_uuid), var as_name = pg_name ++ "_ip4", // avoid name collisions with user-defined Address_Sets not nb::Address_Set(.name = as_name), - var port_uuid = FlatMap(pg_ports), PortStaticAddresses(.lsport = port_uuid, .ip4addrs = stat), SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), @@ -746,11 +745,10 @@ sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :- not nb::Address_Set(.name = as_name). sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :- - nb::Port_Group(.ports = pg_ports, .name = pg_name), + PortGroupPort(.pg_name = pg_name, .port = port_uuid), var as_name = pg_name ++ "_ip6", // avoid name collisions with user-defined Address_Sets not nb::Address_Set(.name = as_name), - var port_uuid = FlatMap(pg_ports), PortStaticAddresses(.lsport = port_uuid, .ip6addrs = stat), SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), @@ -779,9 +777,18 @@ sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :- * SB Port_Group.name uniqueness constraint, ovn-northd populates the field * with the value: _. */ + +relation PortGroupPort( + pg_uuid: uuid, + pg_name: string, + port: uuid) + +PortGroupPort(pg_uuid, pg_name, port) :- + nb::Port_Group(._uuid = pg_uuid, .name = pg_name, .ports = pg_ports), + var port = FlatMap(pg_ports). + sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_names) :- - nb::Port_Group(._uuid = _uuid, .name = nb_name, .ports = pg_ports), - var port_uuid = FlatMap(pg_ports), + PortGroupPort(.pg_uuid = _uuid, .pg_name = nb_name, .port = port_uuid), &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{._uuid = port_uuid, .name = port_name}, .sw = &Switch{.ls = nb::Logical_Switch{._uuid = ls_uuid}}), From patchwork Fri May 7 04:06:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475327 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxlL2ldBz9sPf for ; Fri, 7 May 2021 14:08:46 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A6456419E0; Fri, 7 May 2021 04:08:42 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LmMH2VTOhp17; Fri, 7 May 2021 04:08:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTP id 186FC419BE; Fri, 7 May 2021 04:08:04 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D9127C000F; Fri, 7 May 2021 04:08:03 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0D8DDC000E for ; Fri, 7 May 2021 04:08:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 6256A406B1 for ; Fri, 7 May 2021 04:07:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Vz5-GWUfd86a for ; Fri, 7 May 2021 04:07:35 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 6E551402EE for ; Fri, 7 May 2021 04:07:34 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 7C459C0004; Fri, 7 May 2021 04:07:31 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:48 -0700 Message-Id: <20210507040659.26830-17-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 16/27] ovn-northd-ddlog: Intern the Switch table. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Change the type of record in the `Switch` table from `Ref` to `Intern`. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lswitch.dl | 37 +++++++++++++++++++++---------------- northd/multicast.dl | 10 +++++----- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 27ac3cadc51b..8a37810ae032 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -186,7 +186,7 @@ LogicalSwitchHasNonRouterPort(ls, false) :- /* Switch relation collects all attributes of a logical switch */ -relation &Switch( +typedef Switch = Switch { ls: nb::Logical_Switch, has_stateful_acl: bool, has_lb_vip: bool, @@ -200,7 +200,10 @@ relation &Switch( /* Does this switch have at least one port with type != "router"? */ has_non_router_port: bool -) +} + + +relation Switch[Intern] function ipv6_parse_prefix(s: string): Option { if (string_contains(s, "/")) { @@ -213,17 +216,19 @@ function ipv6_parse_prefix(s: string): Option { } } -&Switch(.ls = ls, - .has_stateful_acl = has_stateful_acl, - .has_lb_vip = has_lb_vip, - .has_dns_records = has_dns_records, - .has_unknown_ports = has_unknown_ports, - .localnet_ports = localnet_ports, - .subnet = subnet, - .ipv6_prefix = ipv6_prefix, - .mcast_cfg = mcast_cfg, - .has_non_router_port = has_non_router_port, - .is_vlan_transparent = is_vlan_transparent) :- +Switch[Switch{ + .ls = ls, + .has_stateful_acl = has_stateful_acl, + .has_lb_vip = has_lb_vip, + .has_dns_records = has_dns_records, + .has_unknown_ports = has_unknown_ports, + .localnet_ports = localnet_ports, + .subnet = subnet, + .ipv6_prefix = ipv6_prefix, + .mcast_cfg = mcast_cfg, + .has_non_router_port = has_non_router_port, + .is_vlan_transparent = is_vlan_transparent + }.intern()] :- nb::Logical_Switch[ls], LogicalSwitchHasStatefulACL(ls._uuid, has_stateful_acl), LogicalSwitchHasLBVIP(ls._uuid, has_lb_vip), @@ -449,7 +454,7 @@ SwitchPortDHCPv6Options(port, options) :- options in &DHCP_OptionsRef[nb::DHCP_Options{._uuid = dhcpv6_uuid}]. /* SwitchQoS: many-to-one relation between logical switches and nb::QoS */ -relation SwitchQoS(sw: Ref, qos: Ref) +relation SwitchQoS(sw: Intern, qos: Ref) SwitchQoS(sw, qos) :- sw in &Switch(.ls = nb::Logical_Switch{.qos_rules = qos_rules}), @@ -475,7 +480,7 @@ ACLWithFairMeter(acl, meter) :- meter in &MeterRef[nb::Meter{.name = meter_name, .fair = Some{true}}]. /* SwitchACL: many-to-many relation between logical switches and ACLs */ -relation &SwitchACL(sw: Ref, +relation &SwitchACL(sw: Intern, acl: Ref, has_fair_meter: bool) @@ -536,7 +541,7 @@ SwitchPortHAChassisGroup(lsp_uuid, None) :- relation &SwitchPort( lsp: nb::Logical_Switch_Port, json_name: string, - sw: Ref, + sw: Intern, peer: Option>, static_addresses: Vec, dynamic_address: Option, diff --git a/northd/multicast.dl b/northd/multicast.dl index 9b0fa80738d7..5a14a90da1cd 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -100,7 +100,7 @@ relation &McastPortCfg( /* Mapping between Switch and the set of router port uuids on which to flood * IP multicast for relay. */ -relation SwitchMcastFloodRelayPorts(sw: Ref, ports: Set) +relation SwitchMcastFloodRelayPorts(sw: Intern, ports: Set) SwitchMcastFloodRelayPorts(switch, relay_ports) :- &SwitchPort( @@ -124,7 +124,7 @@ SwitchMcastFloodRelayPorts(switch, set_empty()) :- /* Mapping between Switch and the set of port uuids on which to * flood IP multicast statically. */ -relation SwitchMcastFloodPorts(sw: Ref, ports: Set) +relation SwitchMcastFloodPorts(sw: Intern, ports: Set) SwitchMcastFloodPorts(switch, flood_ports) :- &SwitchPort( @@ -142,7 +142,7 @@ SwitchMcastFloodPorts(switch, set_empty()) :- /* Mapping between Switch and the set of port uuids on which to * flood IP multicast reports statically. */ -relation SwitchMcastFloodReportPorts(sw: Ref, ports: Set) +relation SwitchMcastFloodReportPorts(sw: Intern, ports: Set) SwitchMcastFloodReportPorts(switch, flood_ports) :- &SwitchPort( @@ -179,7 +179,7 @@ RouterMcastFloodPorts(router, set_empty()) :- /* Flattened IGMP group. One record per address-port tuple. */ relation IgmpSwitchGroupPort( address: string, - switch : Ref, + switch : Intern, port : uuid ) @@ -199,7 +199,7 @@ IgmpSwitchGroupPort(address, switch, localnet_port.0) :- */ relation IgmpSwitchMulticastGroup( address: string, - switch : Ref, + switch : Intern, ports : Set ) From patchwork Fri May 7 04:06:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475334 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxm11Mxpz9sPf for ; Fri, 7 May 2021 14:09:21 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 4C55243067; Fri, 7 May 2021 04:09:18 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id SPTlf32Vi_fG; Fri, 7 May 2021 04:09:12 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTP id C4313419A9; Fri, 7 May 2021 04:08:44 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 96FD5C000F; Fri, 7 May 2021 04:08:44 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0EF80C000E for ; Fri, 7 May 2021 04:08:43 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 3B195615B9 for ; Fri, 7 May 2021 04:07:47 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sOLZQ2tIQVpD for ; Fri, 7 May 2021 04:07:37 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp3.osuosl.org (Postfix) with ESMTPS id 2B37D60E65 for ; Fri, 7 May 2021 04:07:35 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 48895C000B; Fri, 7 May 2021 04:07:32 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:49 -0700 Message-Id: <20210507040659.26830-18-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 17/27] ovn-northd-ddlog: Remove `ls` field from `Switch`. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk This commit is analogous to 076749c99, but switches instead of routers. `relation Switch` stores the internal representation of a logical switch, consisting of values from the `nb::Logical_Switch` table augmented with some additional fields. We used to do this by copying the entire `Logical_Switch` record inside `Switch`. This proved highly inefficient in scenarios where some of the entities that `Logical_Switch` references (logicl switch ports, ACLs, or QoS rules) change frequently. Every such change modifies the `Logical_Switch` record, which triggers an update of the `Switch` object, which can cause a bunch of rules to update their outputs. As a workaround, we no longer store the entire `Logical_Switch` object in the `Switch` table, and instead only copy its relevant fields. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/ipam.dl | 25 ++-- northd/lswitch.dl | 24 ++- northd/ovn_northd.dl | 342 ++++++++++++++++++++++--------------------- 3 files changed, 203 insertions(+), 188 deletions(-) diff --git a/northd/ipam.dl b/northd/ipam.dl index 589126f81288..e7373f250a7f 100644 --- a/northd/ipam.dl +++ b/northd/ipam.dl @@ -95,18 +95,17 @@ function parse_dynamic_address_request(s: string): Option) /* Add reserved address groups (1) and (2). */ -SwitchIPv4ReservedAddress(.lswitch = ls._uuid, +SwitchIPv4ReservedAddress(.lswitch = sw._uuid, .addr = addr) :- - &Switch(.ls = ls, - .subnet = Some{(_, _, start_ipv4, total_ipv4s)}), + sw in &Switch(.subnet = Some{(_, _, start_ipv4, total_ipv4s)}), var exclude_ips = { var exclude_ips = set_singleton(start_ipv4); exclude_ips.insert(start_ipv4 + total_ipv4s - 1); - match (map_get(ls.other_config, "exclude_ips")) { + match (map_get(sw.other_config, "exclude_ips")) { None -> exclude_ips, Some{exclude_ip_list} -> match (parse_ip_list(exclude_ip_list)) { Left{err} -> { - warn("logical switch ${uuid2str(ls._uuid)}: bad exclude_ips (${err})"); + warn("logical switch ${uuid2str(sw._uuid)}: bad exclude_ips (${err})"); exclude_ips }, Right{ranges} -> { @@ -124,7 +123,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, exclude_ips.insert(addr) } } else { - warn("logical switch ${uuid2str(ls._uuid)}: excluded addresses not in subnet") + warn("logical switch ${uuid2str(sw._uuid)}: excluded addresses not in subnet") } }; exclude_ips @@ -135,11 +134,11 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, var addr = FlatMap(exclude_ips). /* Add reserved address group (3). */ -SwitchIPv4ReservedAddress(.lswitch = ls._uuid, +SwitchIPv4ReservedAddress(.lswitch = ls_uuid, .addr = addr) :- SwitchPortStaticAddresses( .port = &SwitchPort{ - .sw = &Switch{.ls = ls, + .sw = &Switch{._uuid = ls_uuid, .subnet = Some{(_, _, start_ipv4, total_ipv4s)}}, .peer = None}, .addrs = lport_addrs @@ -157,10 +156,10 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, var addr = FlatMap(addrs). /* Add reserved address group (4) */ -SwitchIPv4ReservedAddress(.lswitch = ls._uuid, +SwitchIPv4ReservedAddress(.lswitch = ls_uuid, .addr = addr) :- &SwitchPort( - .sw = &Switch{.ls = ls, + .sw = &Switch{._uuid = ls_uuid, .subnet = Some{(_, _, start_ipv4, total_ipv4s)}}, .peer = Some{&rport}), var addrs = { @@ -176,7 +175,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, var addr = FlatMap(addrs). /* Add reserved address group (5) */ -SwitchIPv4ReservedAddress(.lswitch = sw.ls._uuid, +SwitchIPv4ReservedAddress(.lswitch = sw._uuid, .addr = ip_addr.a) :- &SwitchPort(.sw = &sw, .lsp = lsp, .static_dynamic_ipv4 = Some{ip_addr}). @@ -199,7 +198,7 @@ SwitchPortAllocatedIPv4DynAddress(lsport, dyn_addr) :- /* Aggregate all ports of a switch that need a dynamic IP address */ port in &SwitchPort(.needs_dynamic_ipv4address = true, .sw = &sw), - var switch_id = sw.ls._uuid, + var switch_id = sw._uuid, var ports = port.group_by(switch_id).to_vec(), SwitchIPv4ReservedAddresses(switch_id, reserved_addrs), /* Allocate dynamic addresses only for ports that don't have a dynamic address @@ -437,7 +436,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, mac_addr) :- None -> None, Some{addr} -> { if (sw.subnet.is_some() or sw.ipv6_prefix.is_some() or - map_get(sw.ls.other_config, "mac_only") == Some{"true"}) { + map_get(sw.other_config, "mac_only") == Some{"true"}) { Some{addr} } else { None diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 8a37810ae032..b5f53412d313 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -187,7 +187,14 @@ LogicalSwitchHasNonRouterPort(ls, false) :- /* Switch relation collects all attributes of a logical switch */ typedef Switch = Switch { - ls: nb::Logical_Switch, + /* Fields copied from nb::Logical_Switch_Port. */ + _uuid: uuid, + name: string, + load_balancer: Set, + other_config: Map, + external_ids: Map, + + /* Additional computed fields. */ has_stateful_acl: bool, has_lb_vip: bool, has_dns_records: bool, @@ -217,7 +224,12 @@ function ipv6_parse_prefix(s: string): Option { } Switch[Switch{ - .ls = ls, + ._uuid = ls._uuid, + .name = ls.name, + .load_balancer = ls.load_balancer, + .other_config = ls.other_config, + .external_ids = ls.external_ids, + .has_stateful_acl = has_stateful_acl, .has_lb_vip = has_lb_vip, .has_dns_records = has_dns_records, @@ -457,7 +469,8 @@ SwitchPortDHCPv6Options(port, options) :- relation SwitchQoS(sw: Intern, qos: Ref) SwitchQoS(sw, qos) :- - sw in &Switch(.ls = nb::Logical_Switch{.qos_rules = qos_rules}), + sw in &Switch(), + nb::Logical_Switch(._uuid = sw._uuid, .qos_rules = qos_rules), var qos_rule = FlatMap(qos_rules), qos in &QoSRef[nb::QoS{._uuid = qos_rule}]. @@ -486,7 +499,7 @@ relation &SwitchACL(sw: Intern, &SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = has_fair_meter) :- LogicalSwitchACL(sw_uuid, acl_uuid), - sw in &Switch(.ls = nb::Logical_Switch{._uuid = sw_uuid}), + sw in &Switch(._uuid = sw_uuid), acl in &ACLRef[nb::ACL{._uuid = acl_uuid}], ACLHasFairMeter(acl, has_fair_meter). @@ -581,7 +594,8 @@ relation &SwitchPort( .hac_group_uuid = hac_group_uuid) :- nb::Logical_Switch_Port[lsp], LogicalSwitchPort(lsp._uuid, lswitch_uuid), - sw in &Switch(.ls = nb::Logical_Switch{._uuid = lswitch_uuid, .other_config = other_config}, + sw in &Switch(._uuid = lswitch_uuid, + .other_config = other_config, .subnet = subnet, .ipv6_prefix = ipv6_prefix), SwitchRouterPeerRef(lsp._uuid, peer), diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 50203de88867..95de5c0c5d70 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -126,7 +126,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, .gateway_chassis = set_empty(), .ha_chassis_group = sp.hac_group_uuid, .options = options, - .datapath = sw.ls._uuid, + .datapath = sw._uuid, .parent_port = lsp.parent_name, .tag = tag, .mac = lsp.addresses, @@ -149,7 +149,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, }, var options = { var options = lsp.options; - match (sw.ls.other_config.get("vlan-passthru")) { + match (sw.other_config.get("vlan-passthru")) { Some{"true"} -> options.insert("vlan-passthru", "true"), _ -> () }; @@ -164,7 +164,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, .gateway_chassis = set_empty(), .ha_chassis_group = None, .options = options, - .datapath = sw.ls._uuid, + .datapath = sw._uuid, .parent_port = lsp.parent_name, .tag = None, .mac = lsp.addresses, @@ -560,7 +560,7 @@ sb::Out_HA_Chassis(ha_chassis_uuid(ha_chassis.chassis_name, hac_uuid), chassis, sb::Out_HA_Chassis_Group(_uuid, name, ha_chassis, set_empty() /* XXX? */, eids) :- sp in &SwitchPort(), sp.lsp.__type == "external", - var ls_uuid = sp.sw.ls._uuid, + var ls_uuid = sp.sw._uuid, Some{var ha_chassis_group_uuid} = sp.lsp.ha_chassis_group, ha_chassis_group in nb::HA_Chassis_Group(._uuid = ha_chassis_group_uuid, .name = name, .external_ids = eids), @@ -791,7 +791,7 @@ sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_nam PortGroupPort(.pg_uuid = _uuid, .pg_name = nb_name, .port = port_uuid), &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{._uuid = port_uuid, .name = port_name}, - .sw = &Switch{.ls = nb::Logical_Switch{._uuid = ls_uuid}}), + .sw = &Switch{._uuid = ls_uuid}), TunKeyAllocation(.datapath = ls_uuid, .tunkey = tunkey), var sb_name = "${tunkey}_${nb_name}", var port_names = port_name.group_by((_uuid, sb_name)).to_set(). @@ -847,9 +847,9 @@ sb::Out_Multicast_Group (._uuid = hash128((datapath,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - &SwitchPort(.lsp = lsp, .sw = &Switch{.ls = ls}), + &SwitchPort(.lsp = lsp, .sw = sw), lsp.is_enabled(), - var datapath = ls._uuid, + var datapath = sw._uuid, var port_ids = lsp._uuid.group_by((datapath)).to_set(), (var name, var tunnel_key) = mC_FLOOD(). @@ -860,10 +860,10 @@ sb::Out_Multicast_Group (._uuid = hash128((datapath,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - &SwitchPort(.lsp = lsp, .sw = &Switch{.ls = ls}), + &SwitchPort(.lsp = lsp, .sw = sw), lsp.is_enabled(), lsp.__type != "router", - var datapath = ls._uuid, + var datapath = sw._uuid, var port_ids = lsp._uuid.group_by((datapath)).to_set(), (var name, var tunnel_key) = mC_FLOOD_L2(). @@ -880,8 +880,8 @@ sb::Out_Multicast_Group (._uuid = hash128((ls,name)), /* Create a multicast group to flood multicast traffic to routers with * multicast relay enabled. */ -sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), - .datapath = sw.ls._uuid, +sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), + .datapath = sw._uuid, .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- @@ -892,8 +892,8 @@ sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), /* Create a multicast group to flood traffic (no reports) to ports with * multicast flood enabled. */ -sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), - .datapath = sw.ls._uuid, +sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), + .datapath = sw._uuid, .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- @@ -904,8 +904,8 @@ sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), /* Create a multicast group to flood reports to ports with * multicast flood_reports enabled. */ -sb::Out_Multicast_Group (._uuid = hash128((sw.ls._uuid,name)), - .datapath = sw.ls._uuid, +sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), + .datapath = sw._uuid, .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- @@ -928,7 +928,7 @@ sb::Out_Multicast_Group (._uuid = hash128((rtr._uuid,name)), /* Create a multicast group for each IGMP group learned by a Switch. * 'tunnel_key' == 0 triggers an ID allocation later. */ -OutProxy_Multicast_Group (.datapath = switch.ls._uuid, +OutProxy_Multicast_Group (.datapath = switch._uuid, .name = address, .ports = port_ids) :- IgmpSwitchMulticastGroup(address, &switch, port_ids). @@ -1694,14 +1694,15 @@ for (f in AggregatedFlow()) { } /* Logical flows for forwarding groups. */ -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, .actions = actions, .external_ids = stage_hint(fg_uuid)) :- sw in &Switch(), - var fg_uuid = FlatMap(sw.ls.forwarding_groups), + nb::Logical_Switch(._uuid = sw._uuid, .forwarding_groups = forwarding_groups), + var fg_uuid = FlatMap(forwarding_groups), fg in nb::Forwarding_Group(._uuid = fg_uuid), not fg.child_port.is_empty(), var __match = "arp.tpa == ${fg.vip} && arp.op == 1", @@ -1723,14 +1724,15 @@ function escape_child_ports(child_port: Set): string { }; escaped.join(",") } -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, .actions = actions, .external_ids = map_empty()) :- sw in &Switch(), - var fg_uuid = FlatMap(sw.ls.forwarding_groups), + nb::Logical_Switch(._uuid = sw._uuid, .forwarding_groups = forwarding_groups), + var fg_uuid = FlatMap(forwarding_groups), fg in nb::Forwarding_Group(._uuid = fg_uuid), not fg.child_port.is_empty(), var __match = "eth.dst == ${fg.vmac}", @@ -1743,7 +1745,7 @@ Flow(.logical_datapath = sw.ls._uuid, for (sw in &Switch()) { if (not sw.is_vlan_transparent) { /* Block logical VLANs. */ - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 100, .__match = "vlan.present", @@ -1752,7 +1754,7 @@ for (sw in &Switch()) { }; /* Broadcast/multicast source address is invalid */ - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 100, .__match = "eth.src[40]", @@ -1809,29 +1811,29 @@ function build_port_security_ipv6_nd_flow( } /* Pre-ACL */ -for (&Switch(.ls =ls)) { +for (&Switch(._uuid =ls_uuid)) { /* Ingress and Egress Pre-ACL Table (Priority 0): Packets are * allowed by default. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "eth.src == $svc_monitor_mac", @@ -1846,7 +1848,7 @@ for (&Switch(.ls =ls)) { for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, .json_name = lsp_name, - .sw = &Switch{.ls = ls, .has_stateful_acl = true})) { + .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) { /* Can't use ct() for router ports. Consider the * following configuration: lp1(10.0.0.2) on * hostA--ls1--lr0--ls2--lp2(10.0.1.2) on hostB, For a @@ -1859,13 +1861,13 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, * as the icmp request went through the logical router * on hostA, not hostB. This would only work with * distributed conntrack state across all chassis. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "ip && outport == ${lsp_name}", @@ -1875,14 +1877,14 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "localnet"}, .json_name = lsp_name, - .sw = &Switch{.ls = ls, .has_stateful_acl = true})) { - Flow(.logical_datapath = ls._uuid, + .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) { + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "ip && outport == ${lsp_name}", @@ -1890,19 +1892,19 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "localnet"}, .external_ids = stage_hint(lsp._uuid)) } -for (&Switch(.ls = ls, .has_stateful_acl = true)) { +for (&Switch(._uuid = ls_uuid, .has_stateful_acl = true)) { /* Ingress and Egress Pre-ACL Table (Priority 110). * * Not to do conntrack on ND and ICMP destination * unreachable packets. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "nd || nd_rs || nd_ra || mldv1 || mldv2 || " "(udp && udp.src == 546 && udp.dst == 547)", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "nd || nd_rs || nd_ra || mldv1 || mldv2 || " @@ -1918,13 +1920,13 @@ for (&Switch(.ls = ls, .has_stateful_acl = true)) { * * 'REGBIT_CONNTRACK_DEFRAG' is set to let the pre-stateful table send * it to conntrack for tracking and defragmentation. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_ACL(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 100, .__match = "ip", @@ -1933,16 +1935,16 @@ for (&Switch(.ls = ls, .has_stateful_acl = true)) { } /* Pre-LB */ -for (&Switch(.ls = ls)) { +for (&Switch(._uuid = ls_uuid)) { /* Do not send ND packets to conntrack */ var __match = "nd || nd_rs || nd_ra || mldv1 || mldv2" in { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = __match, .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = __match, @@ -1951,13 +1953,13 @@ for (&Switch(.ls = ls)) { }; /* Do not send service monitor packets to conntrack. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = "eth.src == $svc_monitor_mac", @@ -1965,13 +1967,13 @@ for (&Switch(.ls = ls)) { .external_ids = map_empty()); /* Allow all packets to go to next tables by default. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_LB(), .priority = 0, .__match = "1", @@ -1979,15 +1981,15 @@ for (&Switch(.ls = ls)) { .external_ids = map_empty()) } -for (&SwitchPort(.lsp = lsp, .json_name = lsp_name, .sw = &Switch{.ls = ls})) +for (&SwitchPort(.lsp = lsp, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid})) if (lsp.__type == "router" or lsp.__type == "localnet") { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = "ip && outport == ${lsp_name}", @@ -2058,7 +2060,7 @@ LoadBalancerEmptyEvents(lb) :- var local_events = local_options.get_bool_def("event", false), global_events or local_events. -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 130, .__match = __match, @@ -2067,7 +2069,7 @@ Flow(.logical_datapath = sw.ls._uuid, SwitchLBVIP(.sw_uuid = sw_uuid, .lb = lb, .vip = vip, .backends = backends), LoadBalancerEmptyEvents(lb), not lb.options.get_bool_def("reject", false), - sw in &Switch(.ls = nb::Logical_Switch{._uuid = sw_uuid}), + sw in &Switch(._uuid = sw_uuid), backends == "", HasEventElbMeter(has_elb_meter), Some {(var __match, var __action)} = build_empty_lb_event_flow( @@ -2103,13 +2105,13 @@ Flow(.logical_datapath = sw.ls._uuid, * add a lflow to drop ct.inv packets. */ for (sw in &Switch(.has_lb_vip = true)) { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PRE_LB(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_NAT()} = 1; next;", .external_ids = map_empty()); - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PRE_LB(), .priority = 100, .__match = "ip", @@ -2122,16 +2124,16 @@ relation LbProtocol[string] LbProtocol["tcp"]. LbProtocol["udp"]. LbProtocol["sctp"]. -for (&Switch(.ls = ls)) { +for (&Switch(._uuid = ls_uuid)) { /* Ingress and Egress pre-stateful Table (Priority 0): Packets are * allowed by default. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_STATEFUL(), .priority = 0, .__match = "1", @@ -2149,14 +2151,14 @@ for (&Switch(.ls = ls)) { * transport port to be used when detecting hairpin packets. */ for (LbProtocol[protocol]) { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 120, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip4 && ${protocol}", .actions = "${rEG_ORIG_DIP_IPV4()} = ip4.dst; " "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 120, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip6 && ${protocol}", @@ -2165,14 +2167,14 @@ for (&Switch(.ls = ls)) { .external_ids = map_empty()) }; - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 110, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1", .actions = "ct_lb;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_STATEFUL(), .priority = 110, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1", @@ -2181,13 +2183,13 @@ for (&Switch(.ls = ls)) { /* If rEGBIT_CONNTRACK_DEFRAG() is set as 1, then the packets should be * sent to conntrack for tracking and defragmentation. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_DEFRAG()} == 1", .actions = "ct_next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PRE_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_DEFRAG()} == 1", @@ -2303,19 +2305,19 @@ for (UseCtInvMatch[use_ct_inv_match]) { true -> ("ct.inv || ", "&& !ct.inv "), false -> ("", ""), } in - for (sw in &Switch(.ls = ls)) + for (sw in &Switch(._uuid = ls_uuid)) var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in { /* Ingress and Egress ACL Table (Priority 0): Packets are allowed by * default. A related rule at priority 1 is added below if there * are any stateful ACLs in this datapath. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 0, .__match = "1", @@ -2344,13 +2346,13 @@ for (UseCtInvMatch[use_ct_inv_match]) { * which will be done by ct_commit() in the "stateful" stage. * Subsequent packets will hit the flow at priority 0 that just * uses "next;". */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 1, .__match = "ip && (!ct.est || (ct.est && ct_label.blocked == 1))", .actions = "${rEGBIT_CONNTRACK_COMMIT()} = 1; next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 1, .__match = "ip && (!ct.est || (ct.est && ct_label.blocked == 1))", @@ -2364,13 +2366,13 @@ for (UseCtInvMatch[use_ct_inv_match]) { * for deletion (bit 0 of ct_label is set). * * This is enforced at a higher priority than ACLs can be defined. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = ct_inv_or ++ "(ct.est && ct.rpl && ct_label.blocked == 1)", .actions = "drop;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = ct_inv_or ++ "(ct.est && ct.rpl && ct_label.blocked == 1)", @@ -2386,14 +2388,14 @@ for (UseCtInvMatch[use_ct_inv_match]) { * direction to hit the currently defined policy from ACLs. * * This is enforced at a higher priority than ACLs can be defined. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "ct.est && !ct.rel && !ct.new " ++ and_not_ct_inv ++ "&& ct.rpl && ct_label.blocked == 0", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "ct.est && !ct.rel && !ct.new " ++ and_not_ct_inv ++ @@ -2412,14 +2414,14 @@ for (UseCtInvMatch[use_ct_inv_match]) { * a dynamically negotiated FTP data channel), but will allow * related traffic such as an ICMP Port Unreachable through * that's generated from a non-listening UDP port. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "!ct.est && ct.rel && !ct.new " ++ and_not_ct_inv ++ "&& ct_label.blocked == 0", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "!ct.est && ct.rel && !ct.new " ++ and_not_ct_inv ++ @@ -2430,13 +2432,13 @@ for (UseCtInvMatch[use_ct_inv_match]) { /* Ingress and Egress ACL Table (Priority 65535). * * Not to do conntrack on ND packets. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "nd || nd_ra || nd_rs || mldv1 || mldv2", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "nd || nd_ra || nd_rs || mldv1 || mldv2", @@ -2448,7 +2450,7 @@ for (UseCtInvMatch[use_ct_inv_match]) { * if the CMS has configured DNS records for the datapath. */ if (sw.has_dns_records) { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "udp.src == 53", @@ -2458,13 +2460,13 @@ for (UseCtInvMatch[use_ct_inv_match]) { /* Add a 34000 priority flow to advance the service monitor reply * packets to skip applying ingress ACLs. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_ACL(), .priority = 34000, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "eth.src == $svc_monitor_mac", @@ -2488,10 +2490,10 @@ for (UseCtInvMatch[use_ct_inv_match]) { input relation AclHintStages[Stage] AclHintStages[s_SWITCH_IN_ACL_HINT()]. AclHintStages[s_SWITCH_OUT_ACL_HINT()]. -for (sw in &Switch(.ls = ls)) { +for (sw in &Switch(._uuid = ls_uuid)) { for (AclHintStages[stage]) { /* In any case, advance to the next stage. */ - Flow(ls._uuid, stage, 0, "1", "next;", map_empty()) + Flow(ls_uuid, stage, 0, "1", "next;", map_empty()) }; for (AclHintStages[stage]) @@ -2500,7 +2502,7 @@ for (sw in &Switch(.ls = ls)) { * or drop ACLs. For allow ACLs, the connection must also be committed * to conntrack so we set REGBIT_ACL_HINT_ALLOW_NEW. */ - Flow(ls._uuid, stage, 7, "ct.new && !ct.est", + Flow(ls_uuid, stage, 7, "ct.new && !ct.est", "${rEGBIT_ACL_HINT_ALLOW_NEW()} = 1; " "${rEGBIT_ACL_HINT_DROP()} = 1; " "next;", map_empty()); @@ -2513,13 +2515,13 @@ for (sw in &Switch(.ls = ls)) { * REGBIT_ACL_HINT_ALLOW_NEW. * - drop ACLs. */ - Flow(ls._uuid, stage, 6, "!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1", + Flow(ls_uuid, stage, 6, "!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1", "${rEGBIT_ACL_HINT_ALLOW_NEW()} = 1; " "${rEGBIT_ACL_HINT_DROP()} = 1; " "next;", map_empty()); /* Not tracked traffic can either be allowed or dropped. */ - Flow(ls._uuid, stage, 5, "!ct.trk", + Flow(ls_uuid, stage, 5, "!ct.trk", "${rEGBIT_ACL_HINT_ALLOW()} = 1; " "${rEGBIT_ACL_HINT_DROP()} = 1; " "next;", map_empty()); @@ -2532,7 +2534,7 @@ for (sw in &Switch(.ls = ls)) { * connection must be committed with ct_label.blocked set so we set * REGBIT_ACL_HINT_BLOCK. */ - Flow(ls._uuid, stage, 4, "!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0", + Flow(ls_uuid, stage, 4, "!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0", "${rEGBIT_ACL_HINT_ALLOW()} = 1; " "${rEGBIT_ACL_HINT_BLOCK()} = 1; " "next;", map_empty()); @@ -2540,10 +2542,10 @@ for (sw in &Switch(.ls = ls)) { /* Not established or established and already blocked connections may * hit drop ACLs. */ - Flow(ls._uuid, stage, 3, "!ct.est", + Flow(ls_uuid, stage, 3, "!ct.est", "${rEGBIT_ACL_HINT_DROP()} = 1; " "next;", map_empty()); - Flow(ls._uuid, stage, 2, "ct.est && ct_label.blocked == 1", + Flow(ls_uuid, stage, 2, "ct.est && ct_label.blocked == 1", "${rEGBIT_ACL_HINT_DROP()} = 1; " "next;", map_empty()); @@ -2551,14 +2553,14 @@ for (sw in &Switch(.ls = ls)) { * drop ACLs in which case the connection must be committed with * ct_label.blocked set. */ - Flow(ls._uuid, stage, 1, "ct.est && ct_label.blocked == 0", + Flow(ls_uuid, stage, 1, "ct.est && ct_label.blocked == 0", "${rEGBIT_ACL_HINT_BLOCK()} = 1; " "next;", map_empty()) } } /* Ingress or Egress ACL Table (Various priorities). */ -for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_meter)) { +for (&SwitchACL(.sw = sw, .acl = &acl, .has_fair_meter = fair_meter)) { /* consider_acl */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in var ingress = acl.direction == "from-lport" in @@ -2573,7 +2575,7 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ * may and then its return traffic would not have an * associated conntrack entry and would return "+invalid". */ if (not has_stateful) { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = acl.__match, @@ -2592,7 +2594,7 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ * by ct_commit in the "stateful" stage) to indicate that the * connection should be allowed to resume. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = "${rEGBIT_ACL_HINT_ALLOW_NEW()} == 1 && (${acl.__match})", @@ -2605,7 +2607,7 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ * proceed to the next table. We use this to ensure that this * connection is still allowed by the currently defined * policy. Match untracked packets too. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = "${rEGBIT_ACL_HINT_ALLOW()} == 1 && (${acl.__match})", @@ -2622,9 +2624,9 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ * connection, then we can simply reject/drop it. */ var __match = "${rEGBIT_ACL_HINT_DROP()} == 1" in if (acl.action == "reject") { - Reject(ls._uuid, pipeline, stage, acl, fair_meter, __match, "") + Reject(sw._uuid, pipeline, stage, acl, fair_meter, __match, "") } else { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = __match ++ " && (${acl.__match})", @@ -2645,9 +2647,9 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ var __match = "${rEGBIT_ACL_HINT_BLOCK()} == 1" in var actions = "ct_commit { ct_label.blocked = 1; }; " in if (acl.action == "reject") { - Reject(ls._uuid, pipeline, stage, acl, fair_meter, __match, actions) + Reject(sw._uuid, pipeline, stage, acl, fair_meter, __match, actions) } else { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = __match ++ " && (${acl.__match})", @@ -2659,9 +2661,9 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ * so a "reject/drop" ACL is simply the "reject/drop" * logical flow action in all cases. */ if (acl.action == "reject") { - Reject(ls._uuid, pipeline, stage, acl, fair_meter, "", "") + Reject(sw._uuid, pipeline, stage, acl, fair_meter, "", "") } else { - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), .__match = acl.__match, @@ -2681,7 +2683,7 @@ for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, (Some{var server_id}, Some{var server_mac}, Some{var lease_time}) = (options.get("server_id"), options.get("server_mac"), options.get("lease_time")) in var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "outport == ${json_string_escape(lsp.name)} " @@ -2701,7 +2703,7 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, /* Get the link local IP of the DHCPv6 server from the * server MAC. */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "outport == ${json_string_escape(lsp.name)} " @@ -2720,26 +2722,26 @@ QoSAction(qos, k, v) :- (var k, var v) = action. /* QoS rules */ -for (&Switch(.ls = ls)) { - Flow(.logical_datapath = ls._uuid, +for (&Switch(._uuid = ls_uuid)) { + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_QOS_MARK(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_QOS_MARK(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_QOS_METER(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_QOS_METER(), .priority = 0, .__match = "1", @@ -2754,7 +2756,7 @@ for (SwitchQoS(.sw = &sw, .qos = &qos)) { /* FIXME: Can value_action be negative? */ for (QoSAction(qos._uuid, key_action, value_action)) { if (key_action == "dscp") { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = qos.priority, .__match = qos.__match, @@ -2788,7 +2790,7 @@ for (SwitchQoS(.sw = &sw, .qos = &qos)) { * * We limit the bandwidth of this flow by adding a meter table. */ - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = stage, .priority = qos.priority, .__match = qos.__match, @@ -2799,16 +2801,16 @@ for (SwitchQoS(.sw = &sw, .qos = &qos)) { } /* stateful rules */ -for (&Switch(.ls = ls)) { +for (&Switch(._uuid = ls_uuid)) { /* Ingress and Egress stateful Table (Priority 0): Packets are * allowed by default. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_STATEFUL(), .priority = 0, .__match = "1", @@ -2819,13 +2821,13 @@ for (&Switch(.ls = ls)) { * committed to conntrack. We always set ct_label.blocked to 0 here as * any packet that makes it this far is part of a connection we * want to allow to continue. */ - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_COMMIT()} == 1", .actions = "ct_commit { ct_label.blocked = 0; }; next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_COMMIT()} == 1", @@ -2906,7 +2908,7 @@ function build_lb_vip_actions(lbvip: Ref, lbvip.lb.protocol); actions0 ++ actions } -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_STATEFUL(), .priority = priority, .__match = __match, @@ -2914,7 +2916,7 @@ Flow(.logical_datapath = sw.ls._uuid, .external_ids = stage_hint(lb._uuid)) :- sw in &Switch(), LBVIPWithStatus[lbvip@&LBVIPWithStatus{.lb = lb}], - sw.ls.load_balancer.contains(lb._uuid), + sw.load_balancer.contains(lb._uuid), var priority = if (lbvip.vip_port != 0) { 120 } else { 110 }, var actions = { /* Store the original destination IP to be used when generating @@ -2947,12 +2949,12 @@ Flow(.logical_datapath = ls_uuid, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- - &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}), + &Switch(._uuid = ls_uuid), var stages = [s_SWITCH_IN_PRE_HAIRPIN(), s_SWITCH_IN_NAT_HAIRPIN(), s_SWITCH_IN_HAIRPIN()], var stage = FlatMap(stages). -for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { +for (&Switch(._uuid = ls_uuid, .has_lb_vip = true)) { /* Check if the packet needs to be hairpinned. * Set REGBIT_HAIRPIN in the original direction and * REGBIT_HAIRPIN_REPLY in the reply direction. @@ -3020,7 +3022,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name, .ps_eth_addresse None -> "next;", Some{id} -> "set_queue(${id}); next;" } in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 50, .__match = __match, @@ -3055,7 +3057,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) " && ip4.src == 0.0.0.0" " && ip4.dst == 255.255.255.255" " && udp.src == 68 && udp.dst == 67" in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = dhcp_match, @@ -3078,7 +3080,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) "inport == ${port.json_name} && eth.src == ${ps.ea} && ip4.src == {" ++ addrs.join(", ") ++ "}" in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = __match, @@ -3093,7 +3095,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) " && ip6.dst == ff02::/16" " && icmp6.type == {131, 135, 143}" in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = dad_match, @@ -3103,7 +3105,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) var __match = "inport == ${port.json_name} && eth.src == ${ps.ea}" ++ build_port_security_ipv6_flow(Ingress, ps.ea, ps.ipv6_addrs) in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = __match, @@ -3113,7 +3115,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) }; var __match = "inport == ${port.json_name} && eth.src == ${ps.ea} && ip" in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 80, .__match = __match, @@ -3161,7 +3163,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) prefix } } in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 90, .__match = __match, @@ -3173,7 +3175,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) var __match = "inport == ${port.json_name} && eth.src == ${ps.ea}" ++ build_port_security_ipv6_nd_flow(ps.ea, ps.ipv6_addrs) in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 90, .__match = __match, @@ -3181,7 +3183,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) .external_ids = stage_hint(port.lsp._uuid)) } }; - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 80, .__match = "inport == ${port.json_name} && (arp || nd)", @@ -3192,14 +3194,14 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) /* Ingress table PORT_SEC_ND and PORT_SEC_IP: Port security - IP and ND, by * default goto next. (priority 0)*/ -for (&Switch(.ls = ls)) { - Flow(.logical_datapath = ls._uuid, +for (&Switch(._uuid = ls_uuid)) { + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 0, .__match = "1", @@ -3214,7 +3216,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name) if lsp.is_enabled() and (lsp.__type == "localnet" or lsp.__type == "vtep")) { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = "inport == ${json_name}", @@ -3235,7 +3237,7 @@ function lsp_is_up(lsp: nb::Logical_Switch_Port): bool = { * - ARP reply from the virtual ip which belongs to a logical * port of type 'virtual' and bind that port. * */ - Flow(.logical_datapath = sp.sw.ls._uuid, + Flow(.logical_datapath = sp.sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = "inport == ${vp.json_name} && " @@ -3278,7 +3280,7 @@ for (CheckLspIsUp[check_lsp_is_up]) { "outport = inport; " "flags.loopback = 1; " "output;" in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, @@ -3297,7 +3299,7 @@ for (CheckLspIsUp[check_lsp_is_up]) { * detect situations where the network is not working as * configured, so dropping the request would frustrate that * intent.) */ - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = __match ++ " && inport == ${json_name}", @@ -3327,7 +3329,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam "output; " "};" in { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, @@ -3336,7 +3338,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam /* Do not reply to a solicitation from the port that owns the * address (otherwise DAD detection will fail). */ - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = __match ++ " && inport == ${json_name}", @@ -3358,7 +3360,7 @@ for (ls in nb::Logical_Switch) { /* Ingress table ARP_ND_RSP: ARP/ND responder for service monitor source ip. * (priority 110)*/ -Flow(.logical_datapath = sp.sw.ls._uuid, +Flow(.logical_datapath = sp.sw._uuid, .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 110, .__match = "arp.tpa == ${svc_mon_src_ip} && arp.op == 1", @@ -3740,7 +3742,7 @@ for (ls in nb::Logical_Switch) { .external_ids = map_empty()) } -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", @@ -3748,7 +3750,7 @@ Flow(.logical_datapath = sw.ls._uuid, .external_ids = map_empty()) :- sw in &Switch(). -for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) +for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = &mcast_cfg) if (mcast_cfg.enabled)) { for (SwitchMcastFloodRelayPorts(sw, relay_ports)) { for (SwitchMcastFloodReportPorts(sw, flood_report_ports)) { @@ -3768,7 +3770,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) } } in { /* Punt IGMP traffic to controller. */ - UniqueFlow[Flow{.logical_datapath = ls._uuid, + UniqueFlow[Flow{.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 100, .__match = "ip4 && ip.proto == 2", @@ -3776,7 +3778,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) .external_ids = map_empty()}]; /* Punt MLD traffic to controller. */ - UniqueFlow[Flow{.logical_datapath = ls._uuid, + UniqueFlow[Flow{.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 100, .__match = "mldv1 || mldv2", @@ -3787,7 +3789,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) * all ports - RFC 4541, section 2.1.2, item 2. */ var flood = json_string_escape(mC_FLOOD().0) in - UniqueFlow[Flow{.logical_datapath = ls._uuid, + UniqueFlow[Flow{.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 85, .__match = "ip4.mcast && ip4.dst == 224.0.0.0/24", @@ -3798,7 +3800,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) * multicast IPs (RFC 4291, 2.7.1). */ var flood = json_string_escape(mC_FLOOD().0) in - UniqueFlow[Flow{.logical_datapath = ls._uuid, + UniqueFlow[Flow{.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 85, .__match = "ip6.mcast_flood", @@ -3837,7 +3839,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) "" } } in - UniqueFlow[Flow{.logical_datapath = ls._uuid, + UniqueFlow[Flow{.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = "ip4.mcast || ip6.mcast", @@ -3891,7 +3893,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { "" } } in - UniqueFlow[Flow{.logical_datapath = sw.ls._uuid, + UniqueFlow[Flow{.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 90, .__match = "eth.mcast && ${ipX} && ${ipX}.dst == ${address}", @@ -3911,7 +3913,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { * chassis, drop ARP requests arriving on localnet ports from X's Ethernet * address, if the ARP request is asking to translate the IP address of a * router port on LS. */ -Flow(.logical_datapath = sp.sw.ls._uuid, +Flow(.logical_datapath = sp.sw._uuid, .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " @@ -3927,7 +3929,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, rp in &SwitchPort(.sw = sp.sw), rp.lsp.__type == "router", SwitchPortIPv4Address(.port = rp, .addr = rp_addr). -Flow(.logical_datapath = sp.sw.ls._uuid, +Flow(.logical_datapath = sp.sw._uuid, .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " @@ -3944,7 +3946,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, rp in &SwitchPort(.sw = sp.sw), rp.lsp.__type == "router", SwitchPortIPv6Address(.port = rp, .addr = rp_addr). -Flow(.logical_datapath = sp.sw.ls._uuid, +Flow(.logical_datapath = sp.sw._uuid, .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " @@ -3978,7 +3980,7 @@ for (ls in nb::Logical_Switch) { for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, .addrs = addrs) if lsp.__type != "external") { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = "eth.dst == ${addrs.ea}", @@ -4019,7 +4021,7 @@ function lrouter_port_ip_reachable(rp: Ref, addr: v46_ip): bool { }; false } -UniqueFlow[Flow{.logical_datapath = sw.ls._uuid, +UniqueFlow[Flow{.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 75, .__match = __match, @@ -4107,7 +4109,7 @@ function get_arp_forward_ips(rp: Ref): (Set, Set) = * delivers to patch ports) but we're bypassing multicast_groups. * (This is why we match against fLAGBIT_NOT_VXLAN() here.) */ -AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, +AnnotatedFlow(.f = Flow{.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = fLAGBIT_NOT_VXLAN() ++ @@ -4126,7 +4128,7 @@ AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, (var all_ips_v4, _) = get_arp_forward_ips(rp), not all_ips_v4.is_empty(), var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0). -AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, +AnnotatedFlow(.f = Flow{.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = fLAGBIT_NOT_VXLAN() ++ @@ -4149,7 +4151,7 @@ AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, .address = Some{addrs}) if lsp.__type != "external") { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = "eth.dst == ${addrs.ea}", @@ -4190,7 +4192,7 @@ for (&SwitchPort(.lsp = lsp, } else { "eth.dst == ${mac}" } in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, @@ -4206,7 +4208,7 @@ for (&SwitchPort(.lsp = lsp, Some{var emac} = nat.nat.external_mac in Some{var nat_mac} = eth_addr_from_string(emac) in var __match = "eth.dst == ${nat_mac} && is_chassis_resident(${json_string_escape(lport)})" in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, @@ -4227,7 +4229,7 @@ for (&SwitchPort(.lsp = lsp, }*/ /* Ingress table L2_LKUP and L2_UNKNOWN: Destination lookup for unknown MACs (priority 0). */ -for (sw in &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid})) { +for (sw in &Switch(._uuid = ls_uuid)) { Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_L2_LKUP(), .priority = 0, @@ -4257,14 +4259,14 @@ for (sw in &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid})) { /* Egress tables PORT_SEC_IP: Egress port security - IP (priority 0) * Egress table PORT_SEC_L2: Egress port security L2 - multicast/broadcast (priority 100). */ -for (&Switch(.ls = ls)) { - Flow(.logical_datapath = ls._uuid, +for (&Switch(._uuid = ls_uuid)) { + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); - Flow(.logical_datapath = ls._uuid, + Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 100, .__match = "eth.mcast", @@ -4288,19 +4290,19 @@ Flow(.logical_datapath = ls_uuid, sp in &SwitchPort(.lsp = nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = ""}, .ps_addresses = vec_empty()). -Flow(.logical_datapath = ls._uuid, +Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_LOOKUP_FDB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()), -Flow(.logical_datapath = ls._uuid, +Flow(.logical_datapath = ls_uuid, .stage = s_SWITCH_IN_PUT_FDB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- - &Switch(.ls = ls). + &Switch(._uuid = ls_uuid). /* Egress table PORT_SEC_IP: Egress port security - IP (priorities 90 and 80) * if port security enabled. @@ -4311,7 +4313,7 @@ Flow(.logical_datapath = ls._uuid, * * Priority 150 rules drop packets to disabled logical ports, so that they * don't even receive multicast or broadcast packets. */ -Flow(.logical_datapath = sw.ls._uuid, +Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 50, .__match = __match, @@ -4334,7 +4336,7 @@ Flow(.logical_datapath = sw.ls._uuid, for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = &sw) if not lsp.is_enabled() and lsp.__type != "external") { - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 150, .__match = "outport == {$json_name}", @@ -4366,7 +4368,7 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam var __match = "outport == ${json_name} && eth.dst == ${ps.ea} && ip4.dst == {255.255.255.255, 224.0.0.0/4, " ++ addrs.join(", ") ++ "}" in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 90, .__match = __match, @@ -4376,7 +4378,7 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam if (ps.ipv6_addrs.len() > 0) { var __match = "outport == ${json_name} && eth.dst == ${ps.ea}" ++ build_port_security_ipv6_flow(Egress, ps.ea, ps.ipv6_addrs) in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 90, .__match = __match, @@ -4384,7 +4386,7 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam .external_ids = stage_hint(lsp._uuid)) }; var __match = "outport == ${json_name} && eth.dst == ${ps.ea} && ip" in - Flow(.logical_datapath = sw.ls._uuid, + Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 80, .__match = __match, @@ -6901,12 +6903,12 @@ Flow(.logical_datapath = lr_uuid, * connects) and if the address in question is reachable from the * router port, add an ARP/ND entry in that router's pipeline. */ for (SwitchPortIPv4Address( - .port = &SwitchPort{.lsp = lsp, .sw = &sw}, + .port = &SwitchPort{.lsp = lsp, .sw = sw}, .ea = ea, .addr = addr) if lsp.__type != "router" and lsp.__type != "virtual" and lsp.is_enabled()) { - for (&SwitchPort(.sw = &Switch{.ls = nb::Logical_Switch{._uuid = sw.ls._uuid}}, + for (&SwitchPort(.sw = &Switch{._uuid = sw._uuid}, .peer = Some{&peer@RouterPort{.router = &peer_router}})) { Some{_} = find_lrp_member_ip(peer.networks, IPv4{addr.addr}) in @@ -6921,12 +6923,12 @@ for (SwitchPortIPv4Address( } for (SwitchPortIPv6Address( - .port = &SwitchPort{.lsp = lsp, .sw = &sw}, + .port = &SwitchPort{.lsp = lsp, .sw = sw}, .ea = ea, .addr = addr) if lsp.__type != "router" and lsp.__type != "virtual" and lsp.is_enabled()) { - for (&SwitchPort(.sw = &Switch{.ls = nb::Logical_Switch{._uuid = sw.ls._uuid}}, + for (&SwitchPort(.sw = &Switch{._uuid = sw._uuid}, .peer = Some{&peer@RouterPort{.router = &peer_router}})) { Some{_} = find_lrp_member_ip(peer.networks, IPv6{addr.addr}) in @@ -7002,12 +7004,12 @@ Flow(.logical_datapath = peer.router._uuid, * the switch in question. */ for (&SwitchPort(.lsp = lsp1, .peer = Some{&peer1@RouterPort{.router = &peer_router}}, - .sw = &sw) + .sw = sw) if lsp1.is_enabled() and not peer_router.options.get_bool_def("dynamic_neigh_routers", false)) { for (&SwitchPort(.lsp = lsp2, .peer = Some{&peer2}, - .sw = &Switch{.ls = nb::Logical_Switch{._uuid = sw.ls._uuid}}) + .sw = &Switch{._uuid = sw._uuid}) /* Skip the router port under consideration. */ if peer2.lrp._uuid != peer1.lrp._uuid) { @@ -7406,7 +7408,7 @@ function get_port_tunkey(map: Map, key: string): Option relation RequestedPortTunKey(datapath: uuid, port: uuid, tunkey: integer) RequestedPortTunKey(datapath, port, tunkey) :- sp in &SwitchPort(), - var datapath = sp.sw.ls._uuid, + var datapath = sp.sw._uuid, var port = sp.lsp._uuid, Some{var tunkey} = get_port_tunkey(sp.lsp.options, "requested-tnl-key"). RequestedPortTunKey(datapath, port, tunkey) :- From patchwork Fri May 7 04:06:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475330 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxlg6Cgrz9sPf for ; Fri, 7 May 2021 14:09:03 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 0D8F883DEB; Fri, 7 May 2021 04:09:02 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uq9T-MLS-NJF; Fri, 7 May 2021 04:08:57 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id 960428447D; Fri, 7 May 2021 04:08:24 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 6B46AC000E; Fri, 7 May 2021 04:08:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CB3EC000E for ; Fri, 7 May 2021 04:08:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 6ABDF40382 for ; Fri, 7 May 2021 04:07:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id H_WV36icVsZQ for ; Fri, 7 May 2021 04:07:47 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1107940E49 for ; Fri, 7 May 2021 04:07:37 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 12676C0006; Fri, 7 May 2021 04:07:34 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:50 -0700 Message-Id: <20210507040659.26830-19-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 18/27] ovn-northd-ddlog: Intern the SwitchPort table. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Change the type of record in the `SwitchPort` table from `Ref` to `Intern`. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/ipam.dl | 22 +++++++-------- northd/lswitch.dl | 64 +++++++++++++++++++++++--------------------- northd/ovn_northd.dl | 2 +- 3 files changed, 46 insertions(+), 42 deletions(-) diff --git a/northd/ipam.dl b/northd/ipam.dl index e7373f250a7f..40d542ec0687 100644 --- a/northd/ipam.dl +++ b/northd/ipam.dl @@ -212,7 +212,7 @@ SwitchPortAllocatedIPv4DynAddress(lsport, dyn_addr) :- Some{port0} -> { match (port0.sw.subnet) { None -> { - abort("needs_dynamic_ipv4address is true, but subnet is undefined in port ${uuid2str(deref(port0).lsp._uuid)}"); + abort("needs_dynamic_ipv4address is true, but subnet is undefined in port ${uuid2str(port0.lsp._uuid)}"); (0, 0) }, Some{(_, _, start_ipv4, total_ipv4s)} -> (start_ipv4, total_ipv4s) @@ -220,27 +220,27 @@ SwitchPortAllocatedIPv4DynAddress(lsport, dyn_addr) :- } }; for (port in ports) { - //warn("port(${deref(port).lsp._uuid})"); - match (deref(port).dynamic_address) { + //warn("port(${port.lsp._uuid})"); + match (port.dynamic_address) { None -> { /* no dynamic address yet -- allocate one now */ - //warn("need_addr(${deref(port).lsp._uuid})"); - need_addr.push(deref(port).lsp._uuid) + //warn("need_addr(${port.lsp._uuid})"); + need_addr.push(port.lsp._uuid) }, Some{dynaddr} -> { match (dynaddr.ipv4_addrs.nth(0)) { None -> { /* dynamic address does not have IPv4 component -- allocate one now */ - //warn("need_addr(${deref(port).lsp._uuid})"); - need_addr.push(deref(port).lsp._uuid) + //warn("need_addr(${port.lsp._uuid})"); + need_addr.push(port.lsp._uuid) }, Some{addr} -> { var haddr = addr.addr.a; if (haddr < start_ipv4 or haddr >= start_ipv4 + total_ipv4s) { - need_addr.push(deref(port).lsp._uuid) + need_addr.push(port.lsp._uuid) } else if (used_addrs.contains(haddr)) { - need_addr.push(deref(port).lsp._uuid); - warn("Duplicate IP set on switch ${deref(port).lsp.name}: ${addr.addr}") + need_addr.push(port.lsp._uuid); + warn("Duplicate IP set on switch ${port.lsp.name}: ${addr.addr}") } else { /* has valid dynamic address -- record it in used_addrs */ used_addrs.insert(haddr); @@ -459,7 +459,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, addr) :- * Dynamic IPv6 address allocation. * `needs_dynamic_ipv6address` -> mac.to_ipv6_eui64(ipv6_prefix) */ -relation SwitchPortNewDynamicAddress(port: Ref, address: Option) +relation SwitchPortNewDynamicAddress(port: Intern, address: Option) SwitchPortNewDynamicAddress(port, None) :- port in &SwitchPort(.lsp = lsp), diff --git a/northd/lswitch.dl b/northd/lswitch.dl index b5f53412d313..a91e7275a4ea 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -25,7 +25,7 @@ import vec function is_enabled(lsp: nb::Logical_Switch_Port): bool { is_enabled(lsp.enabled) } function is_enabled(lsp: Ref): bool { lsp.deref().is_enabled() } function is_enabled(sp: SwitchPort): bool { sp.lsp.is_enabled() } -function is_enabled(sp: Ref): bool { sp.lsp.is_enabled() } +function is_enabled(sp: Intern): bool { sp.lsp.is_enabled() } relation SwitchRouterPeerRef(lsp: uuid, rport: Option>) @@ -445,7 +445,7 @@ LBVIPBackendStatus(lbvip, backend, true) :- /* SwitchPortDHCPv4Options: many-to-one relation between logical switches and DHCPv4 options */ relation SwitchPortDHCPv4Options( - port: Ref, + port: Intern, dhcpv4_options: Ref) SwitchPortDHCPv4Options(port, options) :- @@ -456,7 +456,7 @@ SwitchPortDHCPv4Options(port, options) :- /* SwitchPortDHCPv6Options: many-to-one relation between logical switches and DHCPv4 options */ relation SwitchPortDHCPv6Options( - port: Ref, + port: Intern, dhcpv6_options: Ref) SwitchPortDHCPv6Options(port, options) :- @@ -551,7 +551,7 @@ SwitchPortHAChassisGroup(lsp_uuid, None) :- * - `up` - true if the port is bound to a chassis or has type "" * - 'hac_group_uuid' - uuid of sb::HA_Chassis_Group, only for "external" ports */ -relation &SwitchPort( +typedef SwitchPort = SwitchPort { lsp: nb::Logical_Switch_Port, json_name: string, sw: Intern, @@ -571,27 +571,31 @@ relation &SwitchPort( up: bool, mcast_cfg: Ref, hac_group_uuid: Option -) - -&SwitchPort(.lsp = lsp, - .json_name = json_string_escape(lsp.name), - .sw = sw, - .peer = peer, - .static_addresses = static_addresses, - .dynamic_address = dynamic_address, - .static_dynamic_mac = static_dynamic_mac, - .static_dynamic_ipv4 = static_dynamic_ipv4, - .static_dynamic_ipv6 = static_dynamic_ipv6, - .ps_addresses = ps_addresses, - .ps_eth_addresses = ps_eth_addresses, - .parent_name = parent_name, - .needs_dynamic_ipv4address = needs_dynamic_ipv4address, - .needs_dynamic_macaddress = needs_dynamic_macaddress, - .needs_dynamic_ipv6address = needs_dynamic_ipv6address, - .needs_dynamic_tag = needs_dynamic_tag, - .up = up, - .mcast_cfg = mcast_cfg, - .hac_group_uuid = hac_group_uuid) :- +} + +relation SwitchPort[Intern] + +SwitchPort[SwitchPort{ + .lsp = lsp, + .json_name = json_string_escape(lsp.name), + .sw = sw, + .peer = peer, + .static_addresses = static_addresses, + .dynamic_address = dynamic_address, + .static_dynamic_mac = static_dynamic_mac, + .static_dynamic_ipv4 = static_dynamic_ipv4, + .static_dynamic_ipv6 = static_dynamic_ipv6, + .ps_addresses = ps_addresses, + .ps_eth_addresses = ps_eth_addresses, + .parent_name = parent_name, + .needs_dynamic_ipv4address = needs_dynamic_ipv4address, + .needs_dynamic_macaddress = needs_dynamic_macaddress, + .needs_dynamic_ipv6address = needs_dynamic_ipv6address, + .needs_dynamic_tag = needs_dynamic_tag, + .up = up, + .mcast_cfg = mcast_cfg, + .hac_group_uuid = hac_group_uuid + }.intern()] :- nb::Logical_Switch_Port[lsp], LogicalSwitchPort(lsp._uuid, lswitch_uuid), sw in &Switch(._uuid = lswitch_uuid, @@ -667,7 +671,7 @@ relation &SwitchPort( .hac_group_uuid = hac_group_uuid). /* Switch port port security addresses */ -relation SwitchPortPSAddresses(port: Ref, +relation SwitchPortPSAddresses(port: Intern, ps_addrs: lport_addresses) SwitchPortPSAddresses(port, ps_addrs) :- @@ -676,7 +680,7 @@ SwitchPortPSAddresses(port, ps_addrs) :- /* All static addresses associated with a port parsed into * the lport_addresses data structure */ -relation SwitchPortStaticAddresses(port: Ref, +relation SwitchPortStaticAddresses(port: Intern, addrs: lport_addresses) SwitchPortStaticAddresses(port, addrs) :- port in &SwitchPort(.static_addresses = static_addresses), @@ -684,7 +688,7 @@ SwitchPortStaticAddresses(port, addrs) :- /* All static and dynamic addresses associated with a port parsed into * the lport_addresses data structure */ -relation SwitchPortAddresses(port: Ref, +relation SwitchPortAddresses(port: Intern, addrs: lport_addresses) SwitchPortAddresses(port, addrs) :- SwitchPortStaticAddresses(port, addrs). @@ -715,7 +719,7 @@ SwitchPortAddresses(port, addrs) :- }. /* All static and dynamic IPv4 addresses associated with a port */ -relation SwitchPortIPv4Address(port: Ref, +relation SwitchPortIPv4Address(port: Intern, ea: eth_addr, addr: ipv4_netaddr) @@ -724,7 +728,7 @@ SwitchPortIPv4Address(port, ea, addr) :- var addr = FlatMap(addrs). /* All static and dynamic IPv6 addresses associated with a port */ -relation SwitchPortIPv6Address(port: Ref, +relation SwitchPortIPv6Address(port: Intern, ea: eth_addr, addr: ipv6_netaddr) diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 95de5c0c5d70..502e204f02c5 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -3541,7 +3541,7 @@ function json_string_escape_vec(names: Vec): string * there's more than one localnet port since the C version uses multiple flows * in that case.) */ -function match_dhcp_input(lsp: Ref): (string, string) = +function match_dhcp_input(lsp: Intern): (string, string) = { if (lsp.lsp.__type == "external" and not lsp.sw.localnet_ports.is_empty()) { ("inport == " ++ json_string_escape_vec(lsp.sw.localnet_ports.map(|x| x.1)) ++ " && ", From patchwork Fri May 7 04:06:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475336 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxmD36ZNz9sPf for ; Fri, 7 May 2021 14:09:32 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id D733984570; Fri, 7 May 2021 04:09:29 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id joGd29_awTKh; Fri, 7 May 2021 04:09:27 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTP id A8D7C83D62; Fri, 7 May 2021 04:08:48 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id ABE15C0022; Fri, 7 May 2021 04:08:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1DADEC000F for ; Fri, 7 May 2021 04:08:43 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id B90D884190 for ; Fri, 7 May 2021 04:07:45 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PHau0wzak7PL for ; Fri, 7 May 2021 04:07:43 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id A85F683E57 for ; Fri, 7 May 2021 04:07:39 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id C6D17C0009; Fri, 7 May 2021 04:07:36 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:51 -0700 Message-Id: <20210507040659.26830-20-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 19/27] ovn-northd-ddlog: Intern the RouterPort table. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Change the type of record in the `RouterPort` table from `Ref` to `Intern`. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 37 +++++++++++++++++++++---------------- northd/lswitch.dl | 4 ++-- northd/ovn_northd.dl | 14 +++++++------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 87550c4fcb36..68df41d02a80 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -23,7 +23,7 @@ import lswitch function is_enabled(lr: nb::Logical_Router): bool { is_enabled(lr.enabled) } function is_enabled(lrp: nb::Logical_Router_Port): bool { is_enabled(lrp.enabled) } function is_enabled(rp: RouterPort): bool { rp.lrp.is_enabled() } -function is_enabled(rp: Ref): bool { rp.lrp.is_enabled() } +function is_enabled(rp: Intern): bool { rp.lrp.is_enabled() } /* default logical flow prioriry for distributed routes */ function dROUTE_PRIO(): bit<32> = 400 @@ -585,7 +585,7 @@ RouterPortHasBfd(lrp_uuid, false) :- /* FIXME: what should happen when extract_lrp_networks fails? */ /* RouterPort relation collects all attributes of a logical router port */ -relation &RouterPort( +typedef RouterPort = RouterPort { lrp: nb::Logical_Router_Port, json_name: string, networks: lport_addresses, @@ -594,17 +594,22 @@ relation &RouterPort( peer: RouterPeer, mcast_cfg: Ref, sb_options: Map, - has_bfd: bool) - -&RouterPort(.lrp = lrp, - .json_name = json_string_escape(lrp.name), - .networks = networks, - .router = router, - .is_redirect = is_redirect, - .peer = peer, - .mcast_cfg = mcast_cfg, - .sb_options = sb_options, - .has_bfd = has_bfd) :- + has_bfd: bool +} + +relation RouterPort[Intern] + +RouterPort[RouterPort{ + .lrp = lrp, + .json_name = json_string_escape(lrp.name), + .networks = networks, + .router = router, + .is_redirect = is_redirect, + .peer = peer, + .mcast_cfg = mcast_cfg, + .sb_options = sb_options, + .has_bfd = has_bfd + }.intern()] :- nb::Logical_Router_Port[lrp], Some{var networks} = extract_lrp_networks(lrp.mac, lrp.networks), LogicalRouterPort(lrp._uuid, lrouter_uuid), @@ -615,13 +620,13 @@ relation &RouterPort( RouterPortSbOptions(lrp._uuid, sb_options), RouterPortHasBfd(lrp._uuid, has_bfd). -relation RouterPortNetworksIPv4Addr(port: Ref, addr: ipv4_netaddr) +relation RouterPortNetworksIPv4Addr(port: Intern, addr: ipv4_netaddr) RouterPortNetworksIPv4Addr(port, addr) :- port in &RouterPort(.networks = networks), var addr = FlatMap(networks.ipv4_addrs). -relation RouterPortNetworksIPv6Addr(port: Ref, addr: ipv6_netaddr) +relation RouterPortNetworksIPv6Addr(port: Intern, addr: ipv6_netaddr) RouterPortNetworksIPv6Addr(port, addr) :- port in &RouterPort(.networks = networks), @@ -743,7 +748,7 @@ RouterStaticRoute_(.router = router, typedef route_dst = RouteDst { nexthop: v46_ip, src_ip: v46_ip, - port: Ref, + port: Intern, ecmp_symmetric_reply: bool } diff --git a/northd/lswitch.dl b/northd/lswitch.dl index a91e7275a4ea..6b2ae37a1608 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -27,7 +27,7 @@ function is_enabled(lsp: Ref): bool { lsp.deref().is_en function is_enabled(sp: SwitchPort): bool { sp.lsp.is_enabled() } function is_enabled(sp: Intern): bool { sp.lsp.is_enabled() } -relation SwitchRouterPeerRef(lsp: uuid, rport: Option>) +relation SwitchRouterPeerRef(lsp: uuid, rport: Option>) SwitchRouterPeerRef(lsp, Some{rport}) :- SwitchRouterPeer(lsp, _, lrp), @@ -555,7 +555,7 @@ typedef SwitchPort = SwitchPort { lsp: nb::Logical_Switch_Port, json_name: string, sw: Intern, - peer: Option>, + peer: Option>, static_addresses: Vec, dynamic_address: Option, static_dynamic_mac: Option, diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 502e204f02c5..25d34b3611bc 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -200,7 +200,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, Some{"router"} -> match ((l3dgw_port, opt_chassis, peer)) { (None, None, _) -> set_empty(), (_, _, None) -> set_empty(), - (_, _, Some{rport}) -> get_nat_addresses(deref(rport)) + (_, _, Some{rport}) -> get_nat_addresses(rport) }, Some{nat_addresses} -> { /* Only accept manual specification of ethernet address @@ -241,7 +241,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, (rport.router.options.contains_key("chassis") and not sw.localnet_ports.is_empty())) { false -> set_empty(), - true -> set_singleton(get_garp_nat_addresses(deref(rport))) + true -> set_singleton(get_garp_nat_addresses(rport)) }, None -> set_empty() }, @@ -324,7 +324,7 @@ function get_router_load_balancer_ips(router: Intern) : * external IP addresses of all NAT rules defined on that router, and all * of the IP addresses used in load balancer VIPs defined on that router. */ -function get_nat_addresses(rport: RouterPort): Set = +function get_nat_addresses(rport: Intern): Set = { var addresses = set_empty(); var has_redirect = rport.router.l3dgw_port.is_some(); @@ -399,7 +399,7 @@ function get_nat_addresses(rport: RouterPort): Set = } } -function get_garp_nat_addresses(rport: RouterPort): string = { +function get_garp_nat_addresses(rport: Intern): string = { var garp_info = ["${rport.networks.ea}"]; for (ipv4_addr in rport.networks.ipv4_addrs) { garp_info.push("${ipv4_addr.addr}") @@ -4002,7 +4002,7 @@ for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json /* Returns 'true' if the IP 'addr' is on the same subnet with one of the * IPs configured on the router port. */ -function lrouter_port_ip_reachable(rp: Ref, addr: v46_ip): bool { +function lrouter_port_ip_reachable(rp: Intern, addr: v46_ip): bool { match (addr) { IPv4{ipv4} -> { for (na in rp.networks.ipv4_addrs) { @@ -4051,7 +4051,7 @@ UniqueFlow[Flow{.logical_datapath = sw._uuid, * router port. * Priority: 80. */ -function get_arp_forward_ips(rp: Ref): (Set, Set) = { +function get_arp_forward_ips(rp: Intern): (Set, Set) = { var all_ips_v4 = set_empty(); var all_ips_v6 = set_empty(); @@ -6303,7 +6303,7 @@ for (&Router(._uuid = lr_uuid)) * the following rule. */ relation Route(key: route_key, // matching criteria - port: Ref, // output port + port: Intern, // output port src_ip: v46_ip, // source IP address for output gateway: Option) // next hop (unless being delivered) From patchwork Fri May 7 04:06:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475331 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxln0Gm3z9sPf for ; Fri, 7 May 2021 14:09:09 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id ABDDC41A16; Fri, 7 May 2021 04:09:06 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aVLvrBF7J75k; Fri, 7 May 2021 04:09:02 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id A9E7A41A1C; Fri, 7 May 2021 04:08:31 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 88824C000E; Fri, 7 May 2021 04:08:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2909FC0027 for ; Fri, 7 May 2021 04:08:30 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 999B34050C for ; Fri, 7 May 2021 04:07:42 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IhDDO-SKFtkZ for ; Fri, 7 May 2021 04:07:41 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 4D6C5404DF for ; Fri, 7 May 2021 04:07:41 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 8867AC0007; Fri, 7 May 2021 04:07:38 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:52 -0700 Message-Id: <20210507040659.26830-21-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 20/27] ovn-northd-ddlog: Remove unused function. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lswitch.dl | 1 - 1 file changed, 1 deletion(-) diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 6b2ae37a1608..eeeb968d5d97 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -23,7 +23,6 @@ import ipam import vec function is_enabled(lsp: nb::Logical_Switch_Port): bool { is_enabled(lsp.enabled) } -function is_enabled(lsp: Ref): bool { lsp.deref().is_enabled() } function is_enabled(sp: SwitchPort): bool { sp.lsp.is_enabled() } function is_enabled(sp: Intern): bool { sp.lsp.is_enabled() } From patchwork Fri May 7 04:06:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475338 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxmM3NZbz9sPf for ; Fri, 7 May 2021 14:09:39 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id B4AB460E5C; Fri, 7 May 2021 04:09:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id FhOGlueSmnxf; Fri, 7 May 2021 04:09:34 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTP id 0A79961629; Fri, 7 May 2021 04:08:58 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E2E5AC000E; Fri, 7 May 2021 04:08:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CEA4C0011 for ; Fri, 7 May 2021 04:08:57 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 7DC1C83D69 for ; Fri, 7 May 2021 04:07:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2WeqB3u3UlBl for ; Fri, 7 May 2021 04:07:45 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 136CA83EE4 for ; Fri, 7 May 2021 04:07:42 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 3A634C0006; Fri, 7 May 2021 04:07:39 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:53 -0700 Message-Id: <20210507040659.26830-22-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 21/27] ovn-northd-ddlog: Eliminate remaining Ref's. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Change all remaining occurrences of `Ref` to `Intern` throughout the DDlog code base. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/helpers.dl | 36 +++++++++++++------------- northd/lrouter.dl | 22 ++++++++-------- northd/lswitch.dl | 61 ++++++++++++++++++++++++-------------------- northd/multicast.dl | 49 ++++++++++++++++++++--------------- northd/ovn_northd.dl | 8 +++--- 5 files changed, 95 insertions(+), 81 deletions(-) diff --git a/northd/helpers.dl b/northd/helpers.dl index 32a5526d59d5..49281fcafc9a 100644 --- a/northd/helpers.dl +++ b/northd/helpers.dl @@ -21,40 +21,40 @@ import ovn output relation Warning[string] /* ACLRef: reference to nb::ACL */ -relation &ACLRef[nb::ACL] -&ACLRef[acl] :- nb::ACL[acl]. +relation ACLRef[Intern] +ACLRef[acl.intern()] :- nb::ACL[acl]. /* DHCP_Options: reference to nb::DHCP_Options */ -relation &DHCP_OptionsRef[nb::DHCP_Options] -&DHCP_OptionsRef[options] :- nb::DHCP_Options[options]. +relation DHCP_OptionsRef[Intern] +DHCP_OptionsRef[options.intern()] :- nb::DHCP_Options[options]. /* QoS: reference to nb::QoS */ -relation &QoSRef[nb::QoS] -&QoSRef[qos] :- nb::QoS[qos]. +relation QoSRef[Intern] +QoSRef[qos.intern()] :- nb::QoS[qos]. /* LoadBalancerRef: reference to nb::Load_Balancer */ -relation &LoadBalancerRef[nb::Load_Balancer] -&LoadBalancerRef[lb] :- nb::Load_Balancer[lb]. +relation LoadBalancerRef[Intern] +LoadBalancerRef[lb.intern()] :- nb::Load_Balancer[lb]. /* LoadBalancerHealthCheckRef: reference to nb::Load_Balancer_Health_Check */ -relation &LoadBalancerHealthCheckRef[nb::Load_Balancer_Health_Check] -&LoadBalancerHealthCheckRef[lbhc] :- nb::Load_Balancer_Health_Check[lbhc]. +relation LoadBalancerHealthCheckRef[Intern] +LoadBalancerHealthCheckRef[lbhc.intern()] :- nb::Load_Balancer_Health_Check[lbhc]. /* MeterRef: reference to nb::Meter*/ -relation &MeterRef[nb::Meter] -&MeterRef[meter] :- nb::Meter[meter]. +relation MeterRef[Intern] +MeterRef[meter.intern()] :- nb::Meter[meter]. /* NATRef: reference to nb::NAT*/ -relation &NATRef[nb::NAT] -&NATRef[nat] :- nb::NAT[nat]. +relation NATRef[Intern] +NATRef[nat.intern()] :- nb::NAT[nat]. /* AddressSetRef: reference to nb::Address_Set */ -relation &AddressSetRef[nb::Address_Set] -&AddressSetRef[__as] :- nb::Address_Set[__as]. +relation AddressSetRef[Intern] +AddressSetRef[__as.intern()] :- nb::Address_Set[__as]. /* ServiceMonitor: reference to sb::Service_Monitor */ -relation &ServiceMonitorRef[sb::Service_Monitor] -&ServiceMonitorRef[sm] :- sb::Service_Monitor[sm]. +relation ServiceMonitorRef[Intern] +ServiceMonitorRef[sm.intern()] :- sb::Service_Monitor[sm]. /* Switch-to-router logical port connections */ relation SwitchRouterPeer(lsp: uuid, lsp_name: string, lrp: uuid) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 68df41d02a80..1b892f8c2e02 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -263,11 +263,11 @@ LogicalRouterRedirectPort(lr, None) :- nb::Logical_Router(._uuid = lr), not DistributedGatewayPort(_, lr). -typedef ExceptionalExtIps = AllowedExtIps{ips: Ref} - | ExemptedExtIps{ips: Ref} +typedef ExceptionalExtIps = AllowedExtIps{ips: Intern} + | ExemptedExtIps{ips: Intern} typedef NAT = NAT{ - nat: Ref, + nat: Intern, external_ip: v46_ip, external_mac: Option, exceptional_ext_ips: Option @@ -275,7 +275,7 @@ typedef NAT = NAT{ relation LogicalRouterNAT0( lr: uuid, - nat: Ref, + nat: Intern, external_ip: v46_ip, external_mac: Option) LogicalRouterNAT0(lr, nat, external_ip, external_mac) :- @@ -409,14 +409,14 @@ LogicalRouterSnatIPs(lr._uuid, map_empty()) :- lr in nb::Logical_Router(), not LogicalRouterSnatIP(.lr = lr._uuid). -relation LogicalRouterLB(lr: uuid, nat: Ref) +relation LogicalRouterLB(lr: uuid, nat: Intern) LogicalRouterLB(lr, lb) :- nb::Logical_Router(._uuid = lr, .load_balancer = lbs), var lb_uuid = FlatMap(lbs), lb in &LoadBalancerRef[nb::Load_Balancer{._uuid = lb_uuid}]. -relation LogicalRouterLBs(lr: uuid, nat: Vec>) +relation LogicalRouterLBs(lr: uuid, nat: Vec>) LogicalRouterLBs(lr, lbs) :- LogicalRouterLB(lr, lb), @@ -458,8 +458,8 @@ typedef Router = Router { is_gateway: bool, nats: Vec, snat_ips: Map>, - lbs: Vec>, - mcast_cfg: Ref, + lbs: Vec>, + mcast_cfg: Intern, learn_from_arp_request: bool, force_lb_snat: bool, } @@ -501,7 +501,7 @@ Router[Router{ var force_lb_snat = lb_force_snat_router_ip(lr.options). /* RouterLB: many-to-many relation between logical routers and nb::LB */ -relation RouterLB(router: Intern, lb: Ref) +relation RouterLB(router: Intern, lb: Intern) RouterLB(router, lb) :- router in &Router(.lbs = lbs), @@ -510,7 +510,7 @@ RouterLB(router, lb) :- /* Load balancer VIPs associated with routers */ relation RouterLBVIP( router: Intern, - lb: Ref, + lb: Intern, vip: string, backends: string) @@ -592,7 +592,7 @@ typedef RouterPort = RouterPort { router: Intern, is_redirect: bool, peer: RouterPeer, - mcast_cfg: Ref, + mcast_cfg: Intern, sb_options: Map, has_bfd: bool } diff --git a/northd/lswitch.dl b/northd/lswitch.dl index eeeb968d5d97..0008c84bbd54 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -201,7 +201,7 @@ typedef Switch = Switch { localnet_ports: Vec<(uuid, string)>, // UUID and name of each localnet port. subnet: Option<(in_addr/*subnet*/, in_addr/*mask*/, bit<32>/*start_ipv4*/, bit<32>/*total_ipv4s*/)>, ipv6_prefix: Option, - mcast_cfg: Ref, + mcast_cfg: Intern, is_vlan_transparent: bool, /* Does this switch have at least one port with type != "router"? */ @@ -276,14 +276,14 @@ Switch[Switch{ var is_vlan_transparent = ls.other_config.get_bool_def("vlan-passthru", false). /* SwitchLB: many-to-many relation between logical switches and nb::LB */ -relation SwitchLB(sw_uuid: uuid, lb: Ref) +relation SwitchLB(sw_uuid: uuid, lb: Intern) SwitchLB(sw_uuid, lb) :- nb::Logical_Switch(._uuid = sw_uuid, .load_balancer = lb_ids), var lb_id = FlatMap(lb_ids), lb in &LoadBalancerRef[nb::Load_Balancer{._uuid = lb_id}]. /* Load balancer VIPs associated with switch */ -relation SwitchLBVIP(sw_uuid: uuid, lb: Ref, vip: string, backends: string) +relation SwitchLBVIP(sw_uuid: uuid, lb: Intern, vip: string, backends: string) SwitchLBVIP(sw_uuid, lb, vip, backends) :- SwitchLB(sw_uuid, lb@(&nb::Load_Balancer{.vips = vips})), var kv = FlatMap(vips), @@ -304,10 +304,10 @@ LogicalSwitchHasLBVIP(sw_uuid, false) :- * - LBVIP parses the IP address and port (and drops VIPs where those are invalid). */ relation LBVIP0( - lb: Ref, + lb: Intern, vip_key: string, backend_ips: string, - health_check: Ref) + health_check: Intern) LBVIP0(lb, vip_key, backend_ips, health_check) :- LoadBalancerRef[lb], var vip = FlatMap(lb.vips), @@ -316,10 +316,10 @@ LBVIP0(lb, vip_key, backend_ips, health_check) :- lb.health_check.contains(health_check._uuid). relation LBVIP1( - lb: Ref, + lb: Intern, vip_key: string, backend_ips: string, - health_check: Option>) + health_check: Option>) LBVIP1(lb, vip_key, backend_ips, Some{health_check}) :- LBVIP0(lb, vip_key, backend_ips, health_check). LBVIP1(lb, vip_key, backend_ips, None) :- @@ -328,15 +328,19 @@ LBVIP1(lb, vip_key, backend_ips, None) :- (var vip_key, var backend_ips) = vip, not LBVIP0(lb, vip_key, backend_ips, _). -relation &LBVIP( - lb: Ref, +typedef LBVIP = LBVIP { + lb: Intern, vip_key: string, backend_ips: string, - health_check: Option>, + health_check: Option>, vip_addr: v46_ip, vip_port: bit<16>, - backends: Vec) -&LBVIP(lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends) :- + backends: Vec +} + +relation LBVIP[Intern] + +LBVIP[LBVIP{lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends}.intern()] :- LBVIP1(lb, vip_key, backend_ips, health_check), Some{(var vip_addr, var vip_port)} = ip_address_and_port_from_lb_key(vip_key), var backends = backend_ips.split(",").filter_map( @@ -398,17 +402,20 @@ function default_protocol(protocol: Option): string = { } } -relation &LBVIPWithStatus( - lb: Ref, +typedef LBVIPWithStatus = LBVIPWithStatus { + lb: Intern, vip_key: string, backend_ips: string, - health_check: Option>, + health_check: Option>, vip_addr: v46_ip, vip_port: bit<16>, - backends: Map) -&LBVIPWithStatus(lb, vip_key, backend_ips, health_check, vip_addr, vip_port, map_empty()) :- + backends: Map +} +relation LBVIPWithStatus[Intern] + +LBVIPWithStatus[LBVIPWithStatus{lb, vip_key, backend_ips, health_check, vip_addr, vip_port, map_empty()}.intern()] :- &LBVIP(lb, vip_key, backend_ips, health_check, vip_addr, vip_port, vec_empty()). -&LBVIPWithStatus(lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends_with_status) :- +LBVIPWithStatus[LBVIPWithStatus{lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends_with_status}.intern()] :- &LBVIP(lb, vip_key, backend_ips, health_check, vip_addr, vip_port, backends), var backend = FlatMap(backends), LBVIPBackendStatus(lbvip, backend, up), @@ -420,7 +427,7 @@ relation &LBVIPWithStatus( * Only some backends have health checking enabled. The ones that don't * are always considered to be up. */ relation LBVIPBackendStatus0( - lbvip: Ref, + lbvip: Intern, backend: lb_vip_backend, up: bool) LBVIPBackendStatus0(lbvip, backend, is_online(sm.status)) :- @@ -433,7 +440,7 @@ LBVIPBackendStatus0(lbvip, backend, is_online(sm.status)) :- default_protocol(lb.protocol) == default_protocol(sm.protocol). relation LBVIPBackendStatus( - lbvip: Ref, + lbvip: Intern, backend: lb_vip_backend, up: bool) LBVIPBackendStatus(lbvip, backend, up) :- LBVIPBackendStatus0(lbvip, backend, up). @@ -445,7 +452,7 @@ LBVIPBackendStatus(lbvip, backend, true) :- /* SwitchPortDHCPv4Options: many-to-one relation between logical switches and DHCPv4 options */ relation SwitchPortDHCPv4Options( port: Intern, - dhcpv4_options: Ref) + dhcpv4_options: Intern) SwitchPortDHCPv4Options(port, options) :- port in &SwitchPort(.lsp = lsp), @@ -456,7 +463,7 @@ SwitchPortDHCPv4Options(port, options) :- /* SwitchPortDHCPv6Options: many-to-one relation between logical switches and DHCPv4 options */ relation SwitchPortDHCPv6Options( port: Intern, - dhcpv6_options: Ref) + dhcpv6_options: Intern) SwitchPortDHCPv6Options(port, options) :- port in &SwitchPort(.lsp = lsp), @@ -465,7 +472,7 @@ SwitchPortDHCPv6Options(port, options) :- options in &DHCP_OptionsRef[nb::DHCP_Options{._uuid = dhcpv6_uuid}]. /* SwitchQoS: many-to-one relation between logical switches and nb::QoS */ -relation SwitchQoS(sw: Intern, qos: Ref) +relation SwitchQoS(sw: Intern, qos: Intern) SwitchQoS(sw, qos) :- sw in &Switch(), @@ -478,7 +485,7 @@ SwitchQoS(sw, qos) :- * that isn't a fair meter. (The latter case has two subcases: the * case where the meter that the ACL names corresponds to an nb::Meter * with that name, and the case where it doesn't.) */ -relation ACLHasFairMeter(acl: Ref, has_fair_meter: bool) +relation ACLHasFairMeter(acl: Intern, has_fair_meter: bool) ACLHasFairMeter(acl, true) :- ACLWithFairMeter(acl, _). ACLHasFairMeter(acl, false) :- @@ -486,14 +493,14 @@ ACLHasFairMeter(acl, false) :- not ACLWithFairMeter(acl, _). /* All the ACLs associated with a fair meter, with their fair meters. */ -relation ACLWithFairMeter(acl: Ref, meter: Ref) +relation ACLWithFairMeter(acl: Intern, meter: Intern) ACLWithFairMeter(acl, meter) :- acl in &ACLRef[nb::ACL{.meter = Some{meter_name}}], meter in &MeterRef[nb::Meter{.name = meter_name, .fair = Some{true}}]. /* SwitchACL: many-to-many relation between logical switches and ACLs */ relation &SwitchACL(sw: Intern, - acl: Ref, + acl: Intern, has_fair_meter: bool) &SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = has_fair_meter) :- @@ -568,7 +575,7 @@ typedef SwitchPort = SwitchPort { needs_dynamic_ipv6address: bool, needs_dynamic_tag: bool, up: bool, - mcast_cfg: Ref, + mcast_cfg: Intern, hac_group_uuid: Option } diff --git a/northd/multicast.dl b/northd/multicast.dl index 5a14a90da1cd..9e3c13a3fde0 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -31,7 +31,7 @@ function mCAST_QUERY_INTERVAL_S_RANGE(): (integer, integer) = (1, 3600) function mCAST_DEFAULT_QUERY_MAX_RESPONSE_S(): integer = 1 /* IP Multicast per switch configuration. */ -relation &McastSwitchCfg( +typedef McastSwitchCfg = McastSwitchCfg { datapath : uuid, enabled : bool, querier : bool, @@ -43,24 +43,27 @@ relation &McastSwitchCfg( idle_timeout : integer, query_interval: integer, query_max_resp: integer -) +} + +relation McastSwitchCfg[Intern] /* FIXME: Right now table_size is enforced only in ovn-controller but in * the ovn-northd C version we enforce it on the aggregate groups too. */ -&McastSwitchCfg( - .datapath = ls_uuid, - .enabled = other_config.get_bool_def("mcast_snoop", false), - .querier = other_config.get_bool_def("mcast_querier", true), - .flood_unreg = other_config.get_bool_def("mcast_flood_unregistered", false), - .eth_src = other_config.get("mcast_eth_src").unwrap_or(""), - .ip4_src = other_config.get("mcast_ip4_src").unwrap_or(""), - .ip6_src = other_config.get("mcast_ip6_src").unwrap_or(""), - .table_size = other_config.get_int_def("mcast_table_size", mCAST_DEFAULT_MAX_ENTRIES()), - .idle_timeout = idle_timeout, - .query_interval = query_interval, - .query_max_resp = query_max_resp) :- +McastSwitchCfg[McastSwitchCfg { + .datapath = ls_uuid, + .enabled = other_config.get_bool_def("mcast_snoop", false), + .querier = other_config.get_bool_def("mcast_querier", true), + .flood_unreg = other_config.get_bool_def("mcast_flood_unregistered", false), + .eth_src = other_config.get("mcast_eth_src").unwrap_or(""), + .ip4_src = other_config.get("mcast_ip4_src").unwrap_or(""), + .ip6_src = other_config.get("mcast_ip6_src").unwrap_or(""), + .table_size = other_config.get_int_def("mcast_table_size", mCAST_DEFAULT_MAX_ENTRIES()), + .idle_timeout = idle_timeout, + .query_interval = query_interval, + .query_max_resp = query_max_resp + }.intern()] :- nb::Logical_Switch(._uuid = ls_uuid, .other_config = other_config), var idle_timeout = other_config.get_int_def("mcast_idle_timeout", mCAST_DEFAULT_IDLE_TIMEOUT_S()) @@ -71,29 +74,33 @@ relation &McastSwitchCfg( mCAST_DEFAULT_QUERY_MAX_RESPONSE_S()). /* IP Multicast per router configuration. */ -relation &McastRouterCfg( +typedef McastRouterCfg = McastRouterCfg { datapath: uuid, relay : bool -) +} -&McastRouterCfg(lr_uuid, mcast_relay) :- +relation McastRouterCfg[Intern] + +McastRouterCfg[McastRouterCfg{lr_uuid, mcast_relay}.intern()] :- nb::Logical_Router(._uuid = lr_uuid, .options = options), var mcast_relay = options.get_bool_def("mcast_relay", false). /* IP Multicast port configuration. */ -relation &McastPortCfg( +typedef McastPortCfg = McastPortCfg { port : uuid, router_port : bool, flood : bool, flood_reports : bool -) +} + +relation McastPortCfg[Intern] -&McastPortCfg(lsp_uuid, false, flood, flood_reports) :- +McastPortCfg[McastPortCfg{lsp_uuid, false, flood, flood_reports}.intern()] :- nb::Logical_Switch_Port(._uuid = lsp_uuid, .options = options), var flood = options.get_bool_def("mcast_flood", false), var flood_reports = options.get_bool_def("mcast_flood_reports", false). -&McastPortCfg(lrp_uuid, true, flood, flood) :- +McastPortCfg[McastPortCfg{lrp_uuid, true, flood, flood}.intern()] :- nb::Logical_Router_Port(._uuid = lrp_uuid, .options = options), var flood = options.get_bool_def("mcast_flood", false). diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 25d34b3611bc..f33d832a4d13 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -303,7 +303,7 @@ function get_router_load_balancer_ips(router: Intern) : var all_ips_v4 = set_empty(); var all_ips_v6 = set_empty(); for (lb in router.lbs) { - for (kv in deref(lb).vips) { + for (kv in lb.vips) { (var vip, _) = kv; /* node->key contains IP:port or just IP. */ match (ip_address_and_port_from_lb_key(vip)) { @@ -2007,7 +2007,7 @@ HasEventElbMeter(false) :- not nb::Meter(.name = "event-elb"). /* Empty LoadBalancer Controller event */ -function build_empty_lb_event_flow(key: string, lb: Ref, +function build_empty_lb_event_flow(key: string, lb: Intern, meter: bool): Option<(string, string)> { (var ip, var port) = match (ip_address_and_port_from_lb_key(key)) { Some{(ip, port)} -> (ip, port), @@ -2052,7 +2052,7 @@ function build_empty_lb_event_flow(key: string, lb: Ref, * The deprecated way is to set nb::NB_Global options:controller_event=true, * which enables events for every load balancer. */ -relation LoadBalancerEmptyEvents(lb: Ref) +relation LoadBalancerEmptyEvents(lb: Intern) LoadBalancerEmptyEvents(lb) :- nb::NB_Global(.options = global_options), var global_events = global_options.get_bool_def("controller_event", false), @@ -2885,7 +2885,7 @@ function ct_lb(backends: string, "ct_lb(" ++ args.join("; ") ++ ");" } -function build_lb_vip_actions(lbvip: Ref, +function build_lb_vip_actions(lbvip: Intern, stage: Stage, actions0: string): string { var up_backends = set_empty(); From patchwork Fri May 7 04:06:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475332 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxlq5H16z9sPf for ; Fri, 7 May 2021 14:09:11 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id CEBDF404C8; Fri, 7 May 2021 04:09:08 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zAgh4y9U6kCm; Fri, 7 May 2021 04:09:05 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id 1EE0D40F75; Fri, 7 May 2021 04:08:53 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C8BDEC000E; Fri, 7 May 2021 04:08:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CB6AC000E for ; Fri, 7 May 2021 04:08:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 0E64A40621 for ; Fri, 7 May 2021 04:07:51 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id G7Bb7smyHFTM for ; Fri, 7 May 2021 04:07:45 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 99F99404EC for ; Fri, 7 May 2021 04:07:44 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id E0D83C0007; Fri, 7 May 2021 04:07:41 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:54 -0700 Message-Id: <20210507040659.26830-23-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 22/27] ovn-northd-ddlog: Eliminate redundant dereferences. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk We eliminate an anti-pattern in the use of smart pointers that occurred throughout the DDlog code. Consider relation `A` that contains field `x` wrapped in a DDlog smart pointer (`Intern<>` or `Ref<>`): ``` relation A(x: Intern, ...) ``` Here `T` might be a complex type with dynamically allocated fields like vectors and maps, etc. Here is how _not_ to use this relation in a rule: ``` Rel(...) :- A(.x = &v), B(v.field1), C(v.field2). ``` The `&v` syntax here extracts the inner value that the smart pointer points to and binds it to variable `v`. Thus, the type of `v` is `T` and we thread the value of `T` through the entire rule, which requires creating two more copies of it (types not wrapped in smart pointers are copied by value). This is a waste of memory and CPU and is completely unnecessary, as we can instead bind `v` to the value of the smart pointer, so it can be copied efficiently: ``` Rel(...) :- A(.x = v), // type of `v` is `Intern`. B(v.field1), C(v.field2). ``` The inefficient usage if a leftover from the days when DDlog had some awkward restrictions on the use of smart pointers. Note that `&` is still useful and does not incur any overhead when used to deconstruct an object wrapped in a smart pointer and refer to its fields, e.g.: ``` Rel(...) :- // Bind `f1` and `f2` to `x.field1` and `x.field2`; // filter out records where `field3` is `false`. A(.x = &T{.field1 = f1, .field2 = f2, .field3 = true}), B(f1), C(f2). ``` On top of this, the `@` operator can be used to simultaneously bind the entire value stored in `x` and its individual fields. ``` Rel(...) :- // Bind `v` to the value of field `x` (`v: Intern`); // bind `f2` to `x.field2`; filter on the value of `field3`. A(.x = v @ &T{.field2 = f2, .field3 = true}), B(v.field1), C(f2). ``` The `&` in this rule is used to deconstruct the value inside the smart pointer; however since the binding operator `@` preceeds `&`, we bind `v` to the value of the smart pointer and not the type that it wraps. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/ipam.dl | 14 +++--- northd/multicast.dl | 4 +- northd/ovn_northd.dl | 104 +++++++++++++++++++++---------------------- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/northd/ipam.dl b/northd/ipam.dl index 40d542ec0687..da71b2872952 100644 --- a/northd/ipam.dl +++ b/northd/ipam.dl @@ -161,7 +161,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls_uuid, &SwitchPort( .sw = &Switch{._uuid = ls_uuid, .subnet = Some{(_, _, start_ipv4, total_ipv4s)}}, - .peer = Some{&rport}), + .peer = Some{rport}), var addrs = { var addrs = set_empty(); for (addr in rport.networks.ipv4_addrs) { @@ -177,7 +177,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls_uuid, /* Add reserved address group (5) */ SwitchIPv4ReservedAddress(.lswitch = sw._uuid, .addr = ip_addr.a) :- - &SwitchPort(.sw = &sw, .lsp = lsp, .static_dynamic_ipv4 = Some{ip_addr}). + &SwitchPort(.sw = sw, .lsp = lsp, .static_dynamic_ipv4 = Some{ip_addr}). /* Aggregate all reserved addresses for each switch. */ relation SwitchIPv4ReservedAddresses(lswitch: uuid, addrs: Set>) @@ -197,7 +197,7 @@ relation SwitchPortAllocatedIPv4DynAddress(lsport: uuid, dyn_addr: Option) SwitchPortNewIPv4DynAddress(lsp._uuid, ip_addr) :- - &SwitchPort(.sw = &sw, + &SwitchPort(.sw = sw, .needs_dynamic_ipv4address = false, .static_dynamic_ipv4 = static_dynamic_ipv4, .lsp = lsp), @@ -333,7 +333,7 @@ ReservedMACAddress(.addr = mac_addr.ha) :- /* Add reserved address group (3). */ ReservedMACAddress(.addr = rport.networks.ea.ha) :- - &SwitchPort(.peer = Some{&rport}). + &SwitchPort(.peer = Some{rport}). /* Aggregate all reserved MAC addresses. */ relation ReservedMACAddresses(addrs: Set>) @@ -430,7 +430,7 @@ relation SwitchPortNewMACDynAddress(lsport: uuid, dyn_addr: Option) SwitchPortNewMACDynAddress(lsp._uuid, mac_addr) :- &SwitchPort(.needs_dynamic_macaddress = false, .lsp = lsp, - .sw = &sw, + .sw = sw, .static_dynamic_mac = static_dynamic_mac), var mac_addr = match (static_dynamic_mac) { None -> None, @@ -467,7 +467,7 @@ SwitchPortNewDynamicAddress(port, None) :- SwitchPortNewDynamicAddress(port, lport_address) :- port in &SwitchPort(.lsp = lsp, - .sw = &sw, + .sw = sw, .needs_dynamic_ipv6address = needs_dynamic_ipv6address, .static_dynamic_ipv6 = static_dynamic_ipv6), SwitchPortNewMACDynAddress(lsp._uuid, Some{mac_addr}), diff --git a/northd/multicast.dl b/northd/multicast.dl index 9e3c13a3fde0..25fcd2938f6b 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -113,7 +113,7 @@ SwitchMcastFloodRelayPorts(switch, relay_ports) :- &SwitchPort( .lsp = lsp, .sw = switch, - .peer = Some{&RouterPort{.router = &Router{.mcast_cfg = &mcast_cfg}}} + .peer = Some{&RouterPort{.router = &Router{.mcast_cfg = mcast_cfg}}} ), mcast_cfg.relay, var relay_ports = lsp._uuid.group_by(switch).to_set(). @@ -236,7 +236,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :- }, var flood_port = FlatMap(sw_flood_ports), &SwitchPort(.lsp = nb::Logical_Switch_Port{._uuid = flood_port}, - .peer = Some{&rtr_port}). + .peer = Some{rtr_port}). /* Aggregated IGMP group for routers: merges all IgmpRouterGroupPort for * a given address-router tuple from all connected switches. diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index f33d832a4d13..99062ea0ceb9 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -132,7 +132,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, .mac = lsp.addresses, .nat_addresses = set_empty(), .external_ids = eids) :- - sp in &SwitchPort(.lsp = lsp, .sw = &sw), + sp in &SwitchPort(.lsp = lsp, .sw = sw), SwitchPortNewDynamicTag(lsp._uuid, opt_tag), var tag = match (opt_tag) { None -> lsp.tag, @@ -170,7 +170,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, .mac = lsp.addresses, .nat_addresses = nat_addresses, .external_ids = eids) :- - &SwitchPort(.lsp = lsp, .sw = &sw, .peer = peer), + &SwitchPort(.lsp = lsp, .sw = sw, .peer = peer), var eids = { var eids = lsp.external_ids; match (lsp.external_ids.get("neutron:port_name")) { @@ -260,7 +260,7 @@ OutProxy_Port_Binding(._uuid = lrp._uuid, .mac = set_singleton("${lrp.mac} ${lrp.networks.join(\" \")}"), .nat_addresses = set_empty(), .external_ids = lrp.external_ids) :- - rp in &RouterPort(.lrp = lrp, .router = &router, .peer = peer), + rp in &RouterPort(.lrp = lrp, .router = router, .peer = peer), RouterPortRAOptionsComplete(lrp._uuid, options0), (var __type, var options1) = match (router.options.get("chassis")) { /* TODO: derived ports */ @@ -885,7 +885,7 @@ sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - SwitchMcastFloodRelayPorts(&sw, port_ids), + SwitchMcastFloodRelayPorts(sw, port_ids), not port_ids.is_empty(), (var name, var tunnel_key) = mC_MROUTER_FLOOD(). @@ -897,7 +897,7 @@ sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - SwitchMcastFloodPorts(&sw, port_ids), + SwitchMcastFloodPorts(sw, port_ids), not port_ids.is_empty(), (var name, var tunnel_key) = mC_STATIC(). @@ -909,7 +909,7 @@ sb::Out_Multicast_Group (._uuid = hash128((sw._uuid,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - SwitchMcastFloodReportPorts(&sw, port_ids), + SwitchMcastFloodReportPorts(sw, port_ids), not port_ids.is_empty(), (var name, var tunnel_key) = mC_MROUTER_STATIC(). @@ -921,7 +921,7 @@ sb::Out_Multicast_Group (._uuid = hash128((rtr._uuid,name)), .name = name, .tunnel_key = tunnel_key, .ports = port_ids) :- - RouterMcastFloodPorts(&rtr, port_ids), + RouterMcastFloodPorts(rtr, port_ids), not port_ids.is_empty(), (var name, var tunnel_key) = mC_STATIC(). @@ -931,7 +931,7 @@ sb::Out_Multicast_Group (._uuid = hash128((rtr._uuid,name)), OutProxy_Multicast_Group (.datapath = switch._uuid, .name = address, .ports = port_ids) :- - IgmpSwitchMulticastGroup(address, &switch, port_ids). + IgmpSwitchMulticastGroup(address, switch, port_ids). /* Create a multicast group for each IGMP group learned by a Router. * 'tunnel_key' == 0 triggers an ID allocation later. @@ -939,7 +939,7 @@ OutProxy_Multicast_Group (.datapath = switch._uuid, OutProxy_Multicast_Group (.datapath = router._uuid, .name = address, .ports = port_ids) :- - IgmpRouterMulticastGroup(address, &router, port_ids). + IgmpRouterMulticastGroup(address, router, port_ids). /* Allocate a 'tunnel_key' for dynamic multicast groups. */ sb::Out_Multicast_Group(._uuid = hash128((mcgroup.datapath,mcgroup.name)), @@ -2202,7 +2202,7 @@ function acl_log_meter_name(meter_name: string, acl_uuid: uuid): string = meter_name ++ "__" ++ uuid2str(acl_uuid) } -function build_acl_log(acl: nb::ACL, fair_meter: bool): string = +function build_acl_log(acl: Intern, fair_meter: bool): string = { if (not acl.log) { "" @@ -2259,7 +2259,7 @@ relation Reject( lsuuid: uuid, pipeline: Pipeline, stage: Stage, - acl: nb::ACL, + acl: Intern, fair_meter: bool, extra_match: string, extra_actions: string) @@ -2560,7 +2560,7 @@ for (sw in &Switch(._uuid = ls_uuid)) { } /* Ingress or Egress ACL Table (Various priorities). */ -for (&SwitchACL(.sw = sw, .acl = &acl, .has_fair_meter = fair_meter)) { +for (&SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = fair_meter)) { /* consider_acl */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in var ingress = acl.direction == "from-lport" in @@ -2677,7 +2677,7 @@ for (&SwitchACL(.sw = sw, .acl = &acl, .has_fair_meter = fair_meter)) { /* Add 34000 priority flow to allow DHCP reply from ovn-controller to all * logical ports of the datapath if the CMS has configured DHCPv4 options. * */ -for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, +for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, .dhcpv4_options = dhcpv4_options@&nb::DHCP_Options{.options = options}) if lsp.__type != "external") { (Some{var server_id}, Some{var server_mac}, Some{var lease_time}) = @@ -2694,7 +2694,7 @@ for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, .external_ids = stage_hint(dhcpv4_options._uuid)) } -for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, +for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, .dhcpv6_options = dhcpv6_options@&nb::DHCP_Options{.options=options} ) if lsp.__type != "external") { Some{var server_mac} = options.get("server_id") in @@ -2749,7 +2749,7 @@ for (&Switch(._uuid = ls_uuid)) { .external_ids = map_empty()) } -for (SwitchQoS(.sw = &sw, .qos = &qos)) { +for (SwitchQoS(.sw = sw, .qos = qos)) { var ingress = if (qos.direction == "from-lport") true else false in var pipeline = if ingress "ingress" else "egress" in { var stage = if (ingress) { s_SWITCH_IN_QOS_MARK() } else { s_SWITCH_OUT_QOS_MARK() } in @@ -3010,7 +3010,7 @@ for (&Switch(._uuid = ls_uuid, .has_lb_vip = true)) { /* Logical switch ingress table PORT_SEC_L2: ingress port security - L2 (priority 50) ingress table PORT_SEC_IP: ingress port security - IP (priority 90 and 80) ingress table PORT_SEC_ND: ingress port security - ND (priority 90 and 80) */ -for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses) +for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses) if lsp.is_enabled() and lsp.__type != "external") { for (pbinding in sb::Out_Port_Binding(.logical_port = lsp.name)) { var __match = if (ps_eth_addresses.is_empty()) { @@ -3046,7 +3046,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name, .ps_eth_addresse * - If the port security has IPv4 addresses or IPv6 addresses or both * - Priority 80 flow to drop all IPv4 and IPv6 traffic */ -for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) +for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) if port.is_enabled() and (ps.ipv4_addrs.len() > 0 or ps.ipv6_addrs.len() > 0) and port.lsp.__type != "external") @@ -3145,7 +3145,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) * * - Priority 80 flow to drop ARP and IPv6 ND packets. */ -for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) +for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) if port.is_enabled() and port.lsp.__type != "external") { var no_ip = ps.ipv4_addrs.is_empty() and ps.ipv6_addrs.is_empty() in @@ -3212,7 +3212,7 @@ for (&Switch(._uuid = ls_uuid)) { /* Ingress table ARP_ND_RSP: ARP/ND responder, skip requests coming from * localnet and vtep ports. (priority 100); see ovn-northd.8.xml for the * rationale. */ -for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name) +for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name) if lsp.is_enabled() and (lsp.__type == "localnet" or lsp.__type == "vtep")) { @@ -3260,7 +3260,7 @@ function lsp_is_up(lsp: nb::Logical_Switch_Port): bool = { * - port type is localport */ for (CheckLspIsUp[check_lsp_is_up]) { - for (SwitchPortIPv4Address(.port = &SwitchPort{.lsp = lsp, .sw = &sw, .json_name = json_name}, + for (SwitchPortIPv4Address(.port = &SwitchPort{.lsp = lsp, .sw = sw, .json_name = json_name}, .ea = ea, .addr = addr) if lsp.is_enabled() and ((lsp_is_up(lsp) or not check_lsp_is_up) @@ -3312,7 +3312,7 @@ for (CheckLspIsUp[check_lsp_is_up]) { /* For ND solicitations, we need to listen for both the * unicast IPv6 address and its all-nodes multicast address, * but always respond with the unicast IPv6 address. */ -for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, +for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw}, .ea = ea, .addr = addr) if lsp.is_enabled() and (lsp_is_up(lsp) or lsp.__type == "router" or lsp.__type == "localport") and @@ -3750,7 +3750,7 @@ Flow(.logical_datapath = sw._uuid, .external_ids = map_empty()) :- sw in &Switch(). -for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = &mcast_cfg) +for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = mcast_cfg) if (mcast_cfg.enabled)) { for (SwitchMcastFloodRelayPorts(sw, relay_ports)) { for (SwitchMcastFloodReportPorts(sw, flood_report_ports)) { @@ -3855,7 +3855,7 @@ for (sw in &Switch(._uuid = ls_uuid, .mcast_cfg = &mcast_cfg) /* Ingress table L2_LKUP: Add IP multicast flows learnt from IGMP/MLD (priority * 90). */ -for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { +for (IgmpSwitchMulticastGroup(.address = address, .switch = sw)) { /* RFC 4541, section 2.1.2, item 2: Skip groups in the 224.0.0.X * range. * @@ -3868,8 +3868,8 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { IPv6{ipv6} -> ipv6.is_all_hosts() } in var ipX = ip.ipX() in - for (SwitchMcastFloodRelayPorts(&sw, relay_ports) if not skip_address) { - for (SwitchMcastFloodPorts(&sw, flood_ports)) { + for (SwitchMcastFloodRelayPorts(sw, relay_ports) if not skip_address) { + for (SwitchMcastFloodPorts(sw, flood_ports)) { var flood_relay = not relay_ports.is_empty() in var flood_static = not flood_ports.is_empty() in var mc_rtr_flood = json_string_escape(mC_MROUTER_FLOOD().0) in @@ -3977,7 +3977,7 @@ for (ls in nb::Logical_Switch) { /* Ingress table L2_LKUP: Destination lookup, unicast handling (priority 50). */ -for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, +for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw}, .addrs = addrs) if lsp.__type != "external") { Flow(.logical_datapath = sw._uuid, @@ -4148,7 +4148,7 @@ AnnotatedFlow(.f = Flow{.logical_datapath = sw._uuid, not all_ips_v6.is_empty(), var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0). -for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, +for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw}, .address = Some{addrs}) if lsp.__type != "external") { Flow(.logical_datapath = sw._uuid, @@ -4161,7 +4161,7 @@ for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = js for (&SwitchPort(.lsp = lsp, .json_name = json_name, - .sw = &sw, + .sw = sw, .peer = Some{&RouterPort{.lrp = lrp, .is_redirect = is_redirect, .router = &Router{._uuid = lr_uuid, @@ -4319,7 +4319,7 @@ Flow(.logical_datapath = sw._uuid, .__match = __match, .actions = queue_action ++ "output;", .external_ids = stage_hint(lsp._uuid)) :- - &SwitchPort(.sw = &sw, .lsp = lsp, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses), + &SwitchPort(.sw = sw, .lsp = lsp, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses), lsp.is_enabled(), lsp.__type != "external", var __match = if (ps_eth_addresses.is_empty()) { @@ -4334,7 +4334,7 @@ Flow(.logical_datapath = sw._uuid, _ -> "" }. -for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = &sw) +for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = sw) if not lsp.is_enabled() and lsp.__type != "external") { Flow(.logical_datapath = sw._uuid, .stage = s_SWITCH_OUT_PORT_SEC_L2(), @@ -4344,7 +4344,7 @@ for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = &sw) .external_ids = stage_hint(lsp._uuid)) } -for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = &sw}, +for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw}, .ps_addrs = ps) if (ps.ipv4_addrs.len() > 0 or ps.ipv6_addrs.len() > 0) and lsp.__type != "external") @@ -4410,7 +4410,7 @@ for (&Router(._uuid = lr_uuid)) { for (&RouterPort(.lrp = lrp, .json_name = json_name, .networks = lrp_networks, - .router = &router, + .router = router, .is_redirect = is_redirect) /* Drop packets from disabled logical ports (since logical flow * tables are default-drop). */ @@ -4614,7 +4614,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { /* Logical router ingress table IP_INPUT: IP Input. */ -for (router in &Router(._uuid = lr_uuid, .mcast_cfg = &mcast_cfg)) { +for (router in &Router(._uuid = lr_uuid, .mcast_cfg = mcast_cfg)) { /* L3 admission control: drop multicast and broadcast source, localhost * source or destination, and zero network source or destination * (priority 100). */ @@ -4732,7 +4732,7 @@ function format_v6_networks(networks: lport_addresses): string = relation AddChassisResidentCheck_(lrp: uuid, add_check: bool) AddChassisResidentCheck_(lrp._uuid, res) :- - &SwitchPort(.peer = Some{&RouterPort{.lrp = lrp, .router = &router, .is_redirect = is_redirect}}, + &SwitchPort(.peer = Some{&RouterPort{.lrp = lrp, .router = router, .is_redirect = is_redirect}}, .sw = sw), router.l3dgw_port.is_some(), not sw.localnet_ports.is_empty(), @@ -4767,7 +4767,7 @@ AddChassisResidentCheck(lrp, false) :- /* Logical router ingress table IP_INPUT: IP Input for IPv4. */ -for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) +for (&RouterPort(.router = router, .networks = networks, .lrp = lrp) if (not networks.ipv4_addrs.is_empty())) { /* L3 admission control: drop packets that originate from an @@ -5178,7 +5178,7 @@ Flow(.logical_datapath = rp.router._uuid, var ipv6_addr = FlatMap(rp.networks.ipv6_addrs). /* Logical router ingress table IP_INPUT: IP Input for IPv6. */ -for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) +for (&RouterPort(.router = router, .networks = networks, .lrp = lrp) if (not networks.ipv6_addrs.is_empty())) { //if (op->derived) { @@ -5294,7 +5294,7 @@ for (RouterPortNetworksIPv6Addr( } /* ICMPv6 time exceeded */ -for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.router = &router, +for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.router = router, .lrp = lrp, .json_name = json_name}, .addr = addr) @@ -6200,7 +6200,7 @@ function copy_ra_to_sb(port: RouterPort, address_mode: string): Map X-Patchwork-Id: 1475335 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxm231wwz9sXS for ; Fri, 7 May 2021 14:09:22 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id B5864419B1; Fri, 7 May 2021 04:09:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qf1nscsUdUT1; Fri, 7 May 2021 04:09:18 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id 343D740637; Fri, 7 May 2021 04:09:11 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 09A6DC000E; Fri, 7 May 2021 04:09:11 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1A986C000E for ; Fri, 7 May 2021 04:09:10 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id AAFE583D96 for ; Fri, 7 May 2021 04:07:57 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EEjE3iKN6rzr for ; Fri, 7 May 2021 04:07:53 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 69CE68430A for ; Fri, 7 May 2021 04:07:46 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 9865AC000B; Fri, 7 May 2021 04:07:43 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:55 -0700 Message-Id: <20210507040659.26830-24-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 23/27] ovn-northd-ddlog: Intern selected input relations. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk DDlog 0.38.0 adds the `--intern-table` CLI flag to the `ovsdb2ddlog` compiler to declare input tables coming from OVSDB as `Intern<...>`. This is useful for tables whose records are copied around as a whole and can therefore benefit from interning performance- and memory-wise. In the past we had to create separate tables in `helpers.dl` and copy records from the original input table to them while wrapping them in `Intern<>`. With this change, we avoid the extra copy and intern records as we ingest them for selected tables. We use the `--intern-table` flag to eliminate all intermediate tables in `helpers.dl`. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/helpers.dl | 36 ------------------------------------ northd/lrouter.dl | 12 ++++++------ northd/lswitch.dl | 26 +++++++++++++------------- northd/ovn-nb.dlopts | 8 ++++++++ northd/ovn-sb.dlopts | 1 + northd/ovn_northd.dl | 30 +++++++++++++++--------------- northd/ovsdb2ddlog2c | 4 +++- 7 files changed, 46 insertions(+), 71 deletions(-) diff --git a/northd/helpers.dl b/northd/helpers.dl index 49281fcafc9a..33a8d15d8b32 100644 --- a/northd/helpers.dl +++ b/northd/helpers.dl @@ -20,42 +20,6 @@ import ovn output relation Warning[string] -/* ACLRef: reference to nb::ACL */ -relation ACLRef[Intern] -ACLRef[acl.intern()] :- nb::ACL[acl]. - -/* DHCP_Options: reference to nb::DHCP_Options */ -relation DHCP_OptionsRef[Intern] -DHCP_OptionsRef[options.intern()] :- nb::DHCP_Options[options]. - -/* QoS: reference to nb::QoS */ -relation QoSRef[Intern] -QoSRef[qos.intern()] :- nb::QoS[qos]. - -/* LoadBalancerRef: reference to nb::Load_Balancer */ -relation LoadBalancerRef[Intern] -LoadBalancerRef[lb.intern()] :- nb::Load_Balancer[lb]. - -/* LoadBalancerHealthCheckRef: reference to nb::Load_Balancer_Health_Check */ -relation LoadBalancerHealthCheckRef[Intern] -LoadBalancerHealthCheckRef[lbhc.intern()] :- nb::Load_Balancer_Health_Check[lbhc]. - -/* MeterRef: reference to nb::Meter*/ -relation MeterRef[Intern] -MeterRef[meter.intern()] :- nb::Meter[meter]. - -/* NATRef: reference to nb::NAT*/ -relation NATRef[Intern] -NATRef[nat.intern()] :- nb::NAT[nat]. - -/* AddressSetRef: reference to nb::Address_Set */ -relation AddressSetRef[Intern] -AddressSetRef[__as.intern()] :- nb::Address_Set[__as]. - -/* ServiceMonitor: reference to sb::Service_Monitor */ -relation ServiceMonitorRef[Intern] -ServiceMonitorRef[sm.intern()] :- sb::Service_Monitor[sm]. - /* Switch-to-router logical port connections */ relation SwitchRouterPeer(lsp: uuid, lsp_name: string, lrp: uuid) SwitchRouterPeer(lsp, lsp_name, lrp) :- diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 1b892f8c2e02..93f02d80bba0 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -281,7 +281,7 @@ relation LogicalRouterNAT0( LogicalRouterNAT0(lr, nat, external_ip, external_mac) :- nb::Logical_Router(._uuid = lr, .nat = nats), var nat_uuid = FlatMap(nats), - nat in &NATRef[nb::NAT{._uuid = nat_uuid}], + nat in &nb::NAT(._uuid = nat_uuid), Some{var external_ip} = ip46_parse(nat.external_ip), var external_mac = match (nat.external_mac) { Some{s} -> eth_addr_from_string(s), @@ -290,12 +290,12 @@ LogicalRouterNAT0(lr, nat, external_ip, external_mac) :- Warning["Bad ip address ${nat.external_ip} in nat configuration for router ${lr_name}."] :- nb::Logical_Router(._uuid = lr, .nat = nats, .name = lr_name), var nat_uuid = FlatMap(nats), - nat in &NATRef[nb::NAT{._uuid = nat_uuid}], + nat in &nb::NAT(._uuid = nat_uuid), None = ip46_parse(nat.external_ip). Warning["Bad MAC address ${s} in nat configuration for router ${lr_name}."] :- nb::Logical_Router(._uuid = lr, .nat = nats, .name = lr_name), var nat_uuid = FlatMap(nats), - nat in &NATRef[nb::NAT{._uuid = nat_uuid}], + nat in &nb::NAT(._uuid = nat_uuid), Some{var s} = nat.external_mac, None = eth_addr_from_string(s). @@ -308,12 +308,12 @@ LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, Some{AllowedExtIps{__as LogicalRouterNAT0(lr, nat, external_ip, external_mac), nat.exempted_ext_ips == None, Some{var __as_uuid} = nat.allowed_ext_ips, - __as in &AddressSetRef[nb::Address_Set{._uuid = __as_uuid}]. + __as in &nb::Address_Set(._uuid = __as_uuid). LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, Some{ExemptedExtIps{__as}}}) :- LogicalRouterNAT0(lr, nat, external_ip, external_mac), nat.allowed_ext_ips == None, Some{var __as_uuid} = nat.exempted_ext_ips, - __as in &AddressSetRef[nb::Address_Set{._uuid = __as_uuid}]. + __as in &nb::Address_Set(._uuid = __as_uuid). Warning["NAT rule: ${nat._uuid} not applied, since" "both allowed and exempt external ips set"] :- LogicalRouterNAT0(lr, nat, _, _), @@ -414,7 +414,7 @@ relation LogicalRouterLB(lr: uuid, nat: Intern) LogicalRouterLB(lr, lb) :- nb::Logical_Router(._uuid = lr, .load_balancer = lbs), var lb_uuid = FlatMap(lbs), - lb in &LoadBalancerRef[nb::Load_Balancer{._uuid = lb_uuid}]. + lb in &nb::Load_Balancer(._uuid = lb_uuid). relation LogicalRouterLBs(lr: uuid, nat: Vec>) diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 0008c84bbd54..29e88d7749f6 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -113,7 +113,7 @@ relation LogicalSwitchStatefulACL(ls: uuid, acl: uuid) LogicalSwitchStatefulACL(ls, acl) :- LogicalSwitchACL(ls, acl), - nb::ACL(._uuid = acl, .action = "allow-related"). + &nb::ACL(._uuid = acl, .action = "allow-related"). relation LogicalSwitchHasStatefulACL(ls: uuid, has_stateful_acl: bool) @@ -280,7 +280,7 @@ relation SwitchLB(sw_uuid: uuid, lb: Intern) SwitchLB(sw_uuid, lb) :- nb::Logical_Switch(._uuid = sw_uuid, .load_balancer = lb_ids), var lb_id = FlatMap(lb_ids), - lb in &LoadBalancerRef[nb::Load_Balancer{._uuid = lb_id}]. + lb in &nb::Load_Balancer(._uuid = lb_id). /* Load balancer VIPs associated with switch */ relation SwitchLBVIP(sw_uuid: uuid, lb: Intern, vip: string, backends: string) @@ -309,10 +309,10 @@ relation LBVIP0( backend_ips: string, health_check: Intern) LBVIP0(lb, vip_key, backend_ips, health_check) :- - LoadBalancerRef[lb], + lb in &nb::Load_Balancer(), var vip = FlatMap(lb.vips), (var vip_key, var backend_ips) = vip, - LoadBalancerHealthCheckRef[health_check@&nb::Load_Balancer_Health_Check{.vip = vip_key}], + health_check in &nb::Load_Balancer_Health_Check(.vip = vip_key), lb.health_check.contains(health_check._uuid). relation LBVIP1( @@ -323,7 +323,7 @@ relation LBVIP1( LBVIP1(lb, vip_key, backend_ips, Some{health_check}) :- LBVIP0(lb, vip_key, backend_ips, health_check). LBVIP1(lb, vip_key, backend_ips, None) :- - LoadBalancerRef[lb], + lb in &nb::Load_Balancer(), var vip = FlatMap(lb.vips), (var vip_key, var backend_ips) = vip, not LBVIP0(lb, vip_key, backend_ips, _). @@ -434,7 +434,7 @@ LBVIPBackendStatus0(lbvip, backend, is_online(sm.status)) :- LBVIP[lbvip@&LBVIP{.lb = lb}], var backend = FlatMap(lbvip.backends), Some{var svc_monitor} = backend.svc_monitor, - sm in sb::Service_Monitor(.port = backend.port as integer), + sm in &sb::Service_Monitor(.port = backend.port as integer), ip46_parse(sm.ip) == Some{backend.ip}, svc_monitor.port_name == sm.logical_port, default_protocol(lb.protocol) == default_protocol(sm.protocol). @@ -458,7 +458,7 @@ SwitchPortDHCPv4Options(port, options) :- port in &SwitchPort(.lsp = lsp), port.lsp.__type != "external", Some{var dhcpv4_uuid} = lsp.dhcpv4_options, - options in &DHCP_OptionsRef[nb::DHCP_Options{._uuid = dhcpv4_uuid}]. + options in &nb::DHCP_Options(._uuid = dhcpv4_uuid). /* SwitchPortDHCPv6Options: many-to-one relation between logical switches and DHCPv4 options */ relation SwitchPortDHCPv6Options( @@ -469,7 +469,7 @@ SwitchPortDHCPv6Options(port, options) :- port in &SwitchPort(.lsp = lsp), port.lsp.__type != "external", Some{var dhcpv6_uuid} = lsp.dhcpv6_options, - options in &DHCP_OptionsRef[nb::DHCP_Options{._uuid = dhcpv6_uuid}]. + options in &nb::DHCP_Options(._uuid = dhcpv6_uuid). /* SwitchQoS: many-to-one relation between logical switches and nb::QoS */ relation SwitchQoS(sw: Intern, qos: Intern) @@ -478,7 +478,7 @@ SwitchQoS(sw, qos) :- sw in &Switch(), nb::Logical_Switch(._uuid = sw._uuid, .qos_rules = qos_rules), var qos_rule = FlatMap(qos_rules), - qos in &QoSRef[nb::QoS{._uuid = qos_rule}]. + qos in &nb::QoS(._uuid = qos_rule). /* Reports whether a given ACL is associated with a fair meter. * 'has_fair_meter' is false if 'acl' has no meter, or if has a meter @@ -489,14 +489,14 @@ relation ACLHasFairMeter(acl: Intern, has_fair_meter: bool) ACLHasFairMeter(acl, true) :- ACLWithFairMeter(acl, _). ACLHasFairMeter(acl, false) :- - acl in &ACLRef[_], + acl in &nb::ACL(), not ACLWithFairMeter(acl, _). /* All the ACLs associated with a fair meter, with their fair meters. */ relation ACLWithFairMeter(acl: Intern, meter: Intern) ACLWithFairMeter(acl, meter) :- - acl in &ACLRef[nb::ACL{.meter = Some{meter_name}}], - meter in &MeterRef[nb::Meter{.name = meter_name, .fair = Some{true}}]. + acl in &nb::ACL(.meter = Some{meter_name}), + meter in &nb::Meter(.name = meter_name, .fair = Some{true}). /* SwitchACL: many-to-many relation between logical switches and ACLs */ relation &SwitchACL(sw: Intern, @@ -506,7 +506,7 @@ relation &SwitchACL(sw: Intern, &SwitchACL(.sw = sw, .acl = acl, .has_fair_meter = has_fair_meter) :- LogicalSwitchACL(sw_uuid, acl_uuid), sw in &Switch(._uuid = sw_uuid), - acl in &ACLRef[nb::ACL{._uuid = acl_uuid}], + acl in &nb::ACL(._uuid = acl_uuid), ACLHasFairMeter(acl, has_fair_meter). function oVN_FEATURE_PORT_UP_NOTIF(): string { "port-up-notif" } diff --git a/northd/ovn-nb.dlopts b/northd/ovn-nb.dlopts index c9c171fe1c84..c4390c904f33 100644 --- a/northd/ovn-nb.dlopts +++ b/northd/ovn-nb.dlopts @@ -13,3 +13,11 @@ --rw NB_Global.ipsec --rw NB_Global.nb_cfg_timestamp --rw NB_Global.hv_cfg_timestamp +--intern-table DHCP_Options +--intern-table ACL +--intern-table QoS +--intern-table Load_Balancer +--intern-table Load_Balancer_Health_Check +--intern-table Meter +--intern-table NAT +--intern-table Address_Set diff --git a/northd/ovn-sb.dlopts b/northd/ovn-sb.dlopts index 1f99118a2b8d..ea4952758b80 100644 --- a/northd/ovn-sb.dlopts +++ b/northd/ovn-sb.dlopts @@ -30,3 +30,4 @@ --ro SB_Global.external_ids --ro SB_Global.ssl --ro Service_Monitor.status +--intern-table Service_Monitor diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 99062ea0ceb9..218ba896dc87 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -35,7 +35,7 @@ for (mb in nb::Meter_Band) { } /* Meter table */ -for (meter in nb::Meter) { +for (meter in &nb::Meter) { sb::Out_Meter(._uuid = meter._uuid, .name = meter.name, .unit = meter.unit, @@ -712,7 +712,7 @@ CheckLspIsUp[true] :- sb::Out_Address_Set(._uuid = nb_as._uuid, .name = nb_as.name, .addresses = nb_as.addresses) :- - AddressSetRef[nb_as]. + nb_as in &nb::Address_Set(). sb::Out_Address_Set(._uuid = hash128("svc_monitor_mac"), .name = "svc_monitor_mac", @@ -723,7 +723,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :- PortGroupPort(.pg_name = pg_name, .port = port_uuid), var as_name = pg_name ++ "_ip4", // avoid name collisions with user-defined Address_Sets - not nb::Address_Set(.name = as_name), + not &nb::Address_Set(.name = as_name), PortStaticAddresses(.lsport = port_uuid, .ip4addrs = stat), SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), @@ -742,13 +742,13 @@ sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :- nb::Port_Group(.ports = set_empty(), .name = pg_name), var as_name = pg_name ++ "_ip4", // avoid name collisions with user-defined Address_Sets - not nb::Address_Set(.name = as_name). + not &nb::Address_Set(.name = as_name). sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :- PortGroupPort(.pg_name = pg_name, .port = port_uuid), var as_name = pg_name ++ "_ip6", // avoid name collisions with user-defined Address_Sets - not nb::Address_Set(.name = as_name), + not &nb::Address_Set(.name = as_name), PortStaticAddresses(.lsport = port_uuid, .ip6addrs = stat), SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), @@ -767,7 +767,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, set_empty()) :- nb::Port_Group(.ports = set_empty(), .name = pg_name), var as_name = pg_name ++ "_ip6", // avoid name collisions with user-defined Address_Sets - not nb::Address_Set(.name = as_name). + not &nb::Address_Set(.name = as_name). /* * Port_Group @@ -2000,11 +2000,11 @@ if (lsp.__type == "router" or lsp.__type == "localnet") { relation HasEventElbMeter(has_meter: bool) HasEventElbMeter(true) :- - nb::Meter(.name = "event-elb"). + &nb::Meter(.name = "event-elb"). HasEventElbMeter(false) :- Unit(), - not nb::Meter(.name = "event-elb"). + not &nb::Meter(.name = "event-elb"). /* Empty LoadBalancer Controller event */ function build_empty_lb_event_flow(key: string, lb: Intern, @@ -2056,7 +2056,7 @@ relation LoadBalancerEmptyEvents(lb: Intern) LoadBalancerEmptyEvents(lb) :- nb::NB_Global(.options = global_options), var global_events = global_options.get_bool_def("controller_event", false), - lb in &LoadBalancerRef[nb::Load_Balancer{.options = local_options}], + lb in &nb::Load_Balancer(.options = local_options), var local_events = local_options.get_bool_def("event", false), global_events or local_events. @@ -2717,7 +2717,7 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, relation QoSAction(qos: uuid, key_action: string, value_action: integer) QoSAction(qos, k, v) :- - nb::QoS(._uuid = qos, .action = actions), + &nb::QoS(._uuid = qos, .action = actions), var action = FlatMap(actions), (var k, var v) = action. @@ -3385,7 +3385,7 @@ Flow(.logical_datapath = sp.sw._uuid, function build_dhcpv4_action( lsp_json_key: string, - dhcpv4_options: nb::DHCP_Options, + dhcpv4_options: Intern, offer_ip: in_addr) : Option<(string, string, string)> = { match (ip_parse_masked(dhcpv4_options.cidr)) { @@ -3443,7 +3443,7 @@ function build_dhcpv4_action( function build_dhcpv6_action( lsp_json_key: string, - dhcpv6_options: nb::DHCP_Options, + dhcpv6_options: Intern, offer_ip: in6_addr): Option<(string, string)> = { match (ipv6_parse_masked(dhcpv6_options.cidr)) { @@ -3570,7 +3570,7 @@ for (lsp in &SwitchPort /* DHCPv4 options enabled for this port */ Some{var dhcpv4_options_uuid} = lsp.lsp.dhcpv4_options in { - for (dhcpv4_options in nb::DHCP_Options(._uuid = dhcpv4_options_uuid)) { + for (dhcpv4_options in &nb::DHCP_Options(._uuid = dhcpv4_options_uuid)) { for (SwitchPortIPv4Address(.port = &SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { Some{(var options_action, var response_action, var ipv4_addr_match)} = build_dhcpv4_action(json_key, dhcpv4_options, addr.addr) in @@ -3627,7 +3627,7 @@ for (lsp in &SwitchPort /* DHCPv6 options enabled for this port */ Some{var dhcpv6_options_uuid} = lsp.lsp.dhcpv6_options in { - for (dhcpv6_options in nb::DHCP_Options(._uuid = dhcpv6_options_uuid)) { + for (dhcpv6_options in &nb::DHCP_Options(._uuid = dhcpv6_options_uuid)) { for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { Some{(var options_action, var response_action)} = build_dhcpv6_action(json_key, dhcpv6_options, addr.addr) in @@ -7726,7 +7726,7 @@ sb::Out_Load_Balancer(._uuid = lb._uuid, nb in nb::Logical_Switch(._uuid = ls_uuid, .load_balancer = lb_uuids), var lb_uuid = FlatMap(lb_uuids), var datapaths = ls_uuid.group_by(lb_uuid).to_set(), - lb in nb::Load_Balancer(._uuid = lb_uuid), + lb in &nb::Load_Balancer(._uuid = lb_uuid), /* Store the fact that northd provides the original (destination IP + * transport port) tuple. */ diff --git a/northd/ovsdb2ddlog2c b/northd/ovsdb2ddlog2c index d0cc7bade9d3..e489c3c760a5 100755 --- a/northd/ovsdb2ddlog2c +++ b/northd/ovsdb2ddlog2c @@ -36,6 +36,7 @@ The following ovsdb2ddlog options are supported: --output-only-table=TABLE Mark TABLE as output-only. DDlog will send updates to this table directly to OVSDB without comparing it with current OVSDB state. --ro=TABLE.COLUMN Ignored. --rw=TABLE.COLUMN Ignored. + --intern-table=TABLE Ignored. --output-file=FILE.inc Write output to FILE.inc. If this option is not specified, output will be written to stdout. The following options are also available: @@ -52,6 +53,7 @@ if __name__ == "__main__": 'schema-file=', 'output-table=', 'output-only-table=', + 'intern-table=', 'ro=', 'rw=', 'output-file=']) @@ -77,7 +79,7 @@ if __name__ == "__main__": output_tables.add(value) elif key == '--output-only-table': output_only_tables.add(value) - elif key in ['--ro', '--rw']: + elif key in ['--ro', '--rw', '--intern-table']: pass elif key == '--output-file': output_file = value From patchwork Fri May 7 04:06:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475337 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxmH5cbHz9sPf for ; Fri, 7 May 2021 14:09:35 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 2336F41505; Fri, 7 May 2021 04:09:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1oIE0fadLf41; Fri, 7 May 2021 04:09:32 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTP id 77B044198E; Fri, 7 May 2021 04:09:26 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E95DFC002B; Fri, 7 May 2021 04:09:23 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3939FC0001 for ; Fri, 7 May 2021 04:09:22 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 358CD83EDF for ; Fri, 7 May 2021 04:08:04 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PQK166GwLbHp for ; Fri, 7 May 2021 04:07:59 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 2AF8383DA6 for ; Fri, 7 May 2021 04:07:47 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 5C661C000E; Fri, 7 May 2021 04:07:45 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:56 -0700 Message-Id: <20210507040659.26830-25-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 24/27] ovn-northd-ddlog: Intern nb::Logical_Router_Port. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Use the `--intern-table` switch to intern `Logical_Router_Port` records, so that they can be copied and compared efficiently by pointer. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/helpers.dl | 2 +- northd/lrouter.dl | 50 ++++++++++++++++++++++---------------------- northd/lswitch.dl | 2 +- northd/multicast.dl | 2 +- northd/ovn-nb.dlopts | 1 + northd/ovn_northd.dl | 34 +++++++++++++++--------------- 6 files changed, 46 insertions(+), 45 deletions(-) diff --git a/northd/helpers.dl b/northd/helpers.dl index 33a8d15d8b32..820e37bb3072 100644 --- a/northd/helpers.dl +++ b/northd/helpers.dl @@ -25,7 +25,7 @@ relation SwitchRouterPeer(lsp: uuid, lsp_name: string, lrp: uuid) SwitchRouterPeer(lsp, lsp_name, lrp) :- nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = "router", .options = options), Some{var router_port} = options.get("router-port"), - nb::Logical_Router_Port(.name = router_port, ._uuid = lrp). + &nb::Logical_Router_Port(.name = router_port, ._uuid = lrp). function get_bool_def(m: Map, k: string, def: bool): bool = { m.get(k) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 93f02d80bba0..3b5047c3ec01 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -21,7 +21,7 @@ import helpers import lswitch function is_enabled(lr: nb::Logical_Router): bool { is_enabled(lr.enabled) } -function is_enabled(lrp: nb::Logical_Router_Port): bool { is_enabled(lrp.enabled) } +function is_enabled(lrp: Intern): bool { is_enabled(lrp.enabled) } function is_enabled(rp: RouterPort): bool { rp.lrp.is_enabled() } function is_enabled(rp: Intern): bool { rp.lrp.is_enabled() } @@ -42,7 +42,7 @@ Warning[message] :- LogicalRouterPortCandidate(lrp_uuid, lr_uuid), var lrs = lr_uuid.group_by(lrp_uuid).to_set(), lrs.size() > 1, - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid), + lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid), var message = "Bad configuration: logical router port ${lrp.name} belongs " "to more than one logical router". @@ -69,9 +69,9 @@ LogicalRouterPort(lrp_uuid, lr_uuid) :- relation PeerLogicalRouter(a: uuid, b: uuid) PeerLogicalRouter(lrp_uuid, peer._uuid) :- LogicalRouterPort(lrp_uuid, _), - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid), + lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid), Some{var peer_name} = lrp.peer, - peer in nb::Logical_Router_Port(.name = peer_name), + peer in &nb::Logical_Router_Port(.name = peer_name), peer.peer == Some{lrp.name}, // 'peer' must point back to 'lrp' lrp_uuid != peer._uuid. // No reflexive pointers. @@ -86,7 +86,7 @@ PeerLogicalRouter(lrp_uuid, peer._uuid) :- relation FirstHopLogicalRouter(lrouter: uuid, lswitch: uuid) FirstHopLogicalRouter(lrouter, lswitch) :- LogicalRouterPort(lrp_uuid, lrouter), - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid, .peer = None), + lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid, .peer = None), LogicalSwitchRouterPort(lsp_uuid, lrp.name, lswitch). relation LogicalSwitchRouterPort(lsp: uuid, lsp_router_port: string, ls: uuid) @@ -119,7 +119,7 @@ ReachableLogicalRouter(a, a) :- ReachableLogicalRouter(a, _). // ha_chassis_group and gateway_chassis may not both be present. Warning[message] :- - lrp in nb::Logical_Router_Port(), + lrp in &nb::Logical_Router_Port(), lrp.ha_chassis_group.is_some(), not lrp.gateway_chassis.is_empty(), var message = "Both ha_chassis_group and gateway_chassis configured on " @@ -127,7 +127,7 @@ Warning[message] :- // A distributed gateway port cannot also be an L3 gateway router. Warning[message] :- - lrp in nb::Logical_Router_Port(), + lrp in &nb::Logical_Router_Port(), lrp.ha_chassis_group.is_some() or not lrp.gateway_chassis.is_empty(), lrp.options.contains_key("chassis"), var message = "Bad configuration: distributed gateway port configured on " @@ -143,7 +143,7 @@ relation DistributedGatewayPortCandidate(lr_uuid: uuid, lrp_uuid: uuid) DistributedGatewayPortCandidate(lr_uuid, lrp_uuid) :- lr in nb::Logical_Router(._uuid = lr_uuid), LogicalRouterPort(lrp_uuid, lr._uuid), - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid), + lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid), not lrp.options.contains_key("chassis"), var has_hcg = lrp.ha_chassis_group.is_some(), var has_gc = not lrp.gateway_chassis.is_empty(), @@ -161,13 +161,13 @@ Warning[message] :- * Each row means 'lrp' is the distributed gateway port on 'lr_uuid'. * * There is at most one distributed gateway port per logical router. */ -relation DistributedGatewayPort(lrp: nb::Logical_Router_Port, lr_uuid: uuid) +relation DistributedGatewayPort(lrp: Intern, lr_uuid: uuid) DistributedGatewayPort(lrp, lr_uuid) :- DistributedGatewayPortCandidate(lr_uuid, lrp_uuid), var lrps = lrp_uuid.group_by(lr_uuid).to_set(), lrps.size() == 1, Some{var lrp_uuid} = lrps.nth(0), - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid). + lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid). /* HAChassis is an abstraction over nb::Gateway_Chassis and nb::HA_Chassis, which * are different ways to represent the same configuration. Each row is @@ -249,12 +249,12 @@ LogicalRouterHAChassisGroup(lr_uuid, /* For each router port, tracks whether it's a redirect port of its router */ relation RouterPortIsRedirect(lrp: uuid, is_redirect: bool) -RouterPortIsRedirect(lrp, true) :- DistributedGatewayPort(nb::Logical_Router_Port{._uuid = lrp}, _). +RouterPortIsRedirect(lrp, true) :- DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, _). RouterPortIsRedirect(lrp, false) :- - nb::Logical_Router_Port(._uuid = lrp), - not DistributedGatewayPort(nb::Logical_Router_Port{._uuid = lrp}, _). + &nb::Logical_Router_Port(._uuid = lrp), + not DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, _). -relation LogicalRouterRedirectPort(lr: uuid, has_redirect_port: Option) +relation LogicalRouterRedirectPort(lr: uuid, has_redirect_port: Option>) LogicalRouterRedirectPort(lr, Some{lrp}) :- DistributedGatewayPort(lrp, lr). @@ -453,7 +453,7 @@ typedef Router = Router { external_ids: Map, /* Additional computed fields. */ - l3dgw_port: Option, + l3dgw_port: Option>, redirect_port_name: string, is_gateway: bool, nats: Vec, @@ -523,9 +523,9 @@ RouterLBVIP(router, lb, vip, backends) :- relation RouterRouterPeer(rport1: uuid, rport2: uuid, rport2_name: string) RouterRouterPeer(rport1, rport2, peer_name) :- - nb::Logical_Router_Port(._uuid = rport1, .peer = peer), + &nb::Logical_Router_Port(._uuid = rport1, .peer = peer), Some{var peer_name} = peer, - nb::Logical_Router_Port(._uuid = rport2, .name = peer_name). + &nb::Logical_Router_Port(._uuid = rport2, .name = peer_name). /* Router port can peer with anothe router port, a switch port or have * no peer. @@ -552,7 +552,7 @@ RouterPortPeer(rport1, PeerRouter{rport2, rport2_name}) :- RouterRouterPeer(rport1, rport2, rport2_name). RouterPortPeer(rport, PeerNone) :- - nb::Logical_Router_Port(._uuid = rport), + &nb::Logical_Router_Port(._uuid = rport), not SwitchRouterPeer(_, _, rport), not RouterRouterPeer(rport, _, _). @@ -563,7 +563,7 @@ RouterPortPeer(rport, PeerNone) :- * faster convergence.) */ relation RouterPortSbOptions(lrp_uuid: uuid, options: Map) RouterPortSbOptions(lrp._uuid, options) :- - lrp in nb::Logical_Router_Port(), + lrp in &nb::Logical_Router_Port(), pb in sb::Port_Binding(._uuid = lrp._uuid), var options = { var options = pb.options; @@ -572,21 +572,21 @@ RouterPortSbOptions(lrp._uuid, options) :- options }. RouterPortSbOptions(lrp._uuid, map_empty()) :- - lrp in nb::Logical_Router_Port(), + lrp in &nb::Logical_Router_Port(), not sb::Port_Binding(._uuid = lrp._uuid). relation RouterPortHasBfd(lrp_uuid: uuid, has_bfd: bool) RouterPortHasBfd(lrp_uuid, true) :- - nb::Logical_Router_Port(._uuid = lrp_uuid, .name = logical_port), + &nb::Logical_Router_Port(._uuid = lrp_uuid, .name = logical_port), nb::BFD(.logical_port = logical_port). RouterPortHasBfd(lrp_uuid, false) :- - nb::Logical_Router_Port(._uuid = lrp_uuid, .name = logical_port), + &nb::Logical_Router_Port(._uuid = lrp_uuid, .name = logical_port), not nb::BFD(.logical_port = logical_port). /* FIXME: what should happen when extract_lrp_networks fails? */ /* RouterPort relation collects all attributes of a logical router port */ typedef RouterPort = RouterPort { - lrp: nb::Logical_Router_Port, + lrp: Intern, json_name: string, networks: lport_addresses, router: Intern, @@ -610,7 +610,7 @@ RouterPort[RouterPort{ .sb_options = sb_options, .has_bfd = has_bfd }.intern()] :- - nb::Logical_Router_Port[lrp], + lrp in &nb::Logical_Router_Port(), Some{var networks} = extract_lrp_networks(lrp.mac, lrp.networks), LogicalRouterPort(lrp._uuid, lrouter_uuid), router in &Router(._uuid = lrouter_uuid), @@ -775,7 +775,7 @@ RouterStaticRoute(router, key, dsts) :- .output_port = Some{oport}, .ecmp_symmetric_reply = ecmp_symmetric_reply), /* output_port specified */ - port in &RouterPort(.lrp = nb::Logical_Router_Port{.name = oport}, + port in &RouterPort(.lrp = &nb::Logical_Router_Port{.name = oport}, .networks = networks), Some{var src_ip} = match (find_lrp_member_ip(networks, nexthop)) { Some{src_ip} -> Some{src_ip}, diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 29e88d7749f6..cc0777f743c1 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -30,7 +30,7 @@ relation SwitchRouterPeerRef(lsp: uuid, rport: Option>) SwitchRouterPeerRef(lsp, Some{rport}) :- SwitchRouterPeer(lsp, _, lrp), - rport in &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp}). + rport in &RouterPort(.lrp = &nb::Logical_Router_Port{._uuid = lrp}). SwitchRouterPeerRef(lsp, None) :- nb::Logical_Switch_Port(._uuid = lsp), diff --git a/northd/multicast.dl b/northd/multicast.dl index 25fcd2938f6b..bd9bc9b46f61 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -101,7 +101,7 @@ McastPortCfg[McastPortCfg{lsp_uuid, false, flood, flood_reports}.intern()] :- var flood_reports = options.get_bool_def("mcast_flood_reports", false). McastPortCfg[McastPortCfg{lrp_uuid, true, flood, flood}.intern()] :- - nb::Logical_Router_Port(._uuid = lrp_uuid, .options = options), + &nb::Logical_Router_Port(._uuid = lrp_uuid, .options = options), var flood = options.get_bool_def("mcast_flood", false). /* Mapping between Switch and the set of router port uuids on which to flood diff --git a/northd/ovn-nb.dlopts b/northd/ovn-nb.dlopts index c4390c904f33..c1ceb4f1496a 100644 --- a/northd/ovn-nb.dlopts +++ b/northd/ovn-nb.dlopts @@ -21,3 +21,4 @@ --intern-table Meter --intern-table NAT --intern-table Address_Set +--intern-table Logical_Router_Port diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 218ba896dc87..f7744a1dae75 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -418,7 +418,7 @@ relation RouterPortRAOptionsComplete(lrp: uuid, options: Map) RouterPortRAOptionsComplete(lrp, options) :- RouterPortRAOptions(lrp, options). RouterPortRAOptionsComplete(lrp, map_empty()) :- - nb::Logical_Router_Port(._uuid = lrp), + &nb::Logical_Router_Port(._uuid = lrp), not RouterPortRAOptions(lrp, _). @@ -1384,7 +1384,7 @@ nb::Out_Logical_Switch_Port(._uuid = lsp._uuid, relation LRPIPv6Prefix0(lrp_uuid: uuid, ipv6_prefix: string) LRPIPv6Prefix0(lrp._uuid, ipv6_prefix) :- - lrp in nb::Logical_Router_Port(), + lrp in &nb::Logical_Router_Port(), lrp.options.get_bool_def("prefix", false), sb::Port_Binding(.logical_port = lrp.name, .options = options), Some{var ipv6_ra_pd_list} = options.get("ipv6_ra_pd_list"), @@ -1395,12 +1395,12 @@ relation LRPIPv6Prefix(lrp_uuid: uuid, ipv6_prefix: Option) LRPIPv6Prefix(lrp_uuid, Some{ipv6_prefix}) :- LRPIPv6Prefix0(lrp_uuid, ipv6_prefix). LRPIPv6Prefix(lrp_uuid, None) :- - nb::Logical_Router_Port(._uuid = lrp_uuid), + &nb::Logical_Router_Port(._uuid = lrp_uuid), not LRPIPv6Prefix0(lrp_uuid, _). nb::Out_Logical_Router_Port(._uuid = _uuid, .ipv6_prefix = to_set(ipv6_prefix)) :- - nb::Logical_Router_Port(._uuid = _uuid, .name = name), + &nb::Logical_Router_Port(._uuid = _uuid, .name = name), LRPIPv6Prefix(_uuid, ipv6_prefix). typedef Pipeline = Ingress | Egress @@ -4762,7 +4762,7 @@ AddChassisResidentCheck(lrp, add_check) :- AddChassisResidentCheck_(lrp, add_check). AddChassisResidentCheck(lrp, false) :- - nb::Logical_Router_Port(._uuid = lrp), + &nb::Logical_Router_Port(._uuid = lrp), not AddChassisResidentCheck_(lrp, _). @@ -4855,7 +4855,7 @@ LogicalRouterPortNatArpNdFlow(router, nat, l3dgw_port) :- /* Respond to ARP/NS requests on the chassis that binds the gw * port. Drop the ARP/NS requests on other chassis. */ -relation LogicalRouterPortNatArpNdFlow(router: Intern, nat: NAT, lrp: nb::Logical_Router_Port) +relation LogicalRouterPortNatArpNdFlow(router: Intern, nat: NAT, lrp: Intern) LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, Some{extra_match}, false, 92), LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :- LogicalRouterPortNatArpNdFlow(router, nat, lrp), @@ -4888,7 +4888,7 @@ LogicalRouterArpNdFlow(router, nat, Some{lrp}, mac, None, true, 91) :- relation LogicalRouterArpNdFlow( router: Intern, nat: NAT, - lrp: Option, + lrp: Option>, mac: string, extra_match: Option, drop: bool, @@ -4904,7 +4904,7 @@ LogicalRouterNdFlow(router, lrp, "nd_na", ipv6, true, mac, extra_match, drop, pr relation LogicalRouterArpFlow( lr: Intern, - lrp: Option, + lrp: Option>, ip: in_addr, mac: string, extra_match: Option, @@ -4947,7 +4947,7 @@ Flow(.logical_datapath = lr._uuid, relation LogicalRouterNdFlow( lr: Intern, - lrp: Option, + lrp: Option>, action: string, ip: in6_addr, sn_ip: bool, @@ -5083,7 +5083,7 @@ Flow(.logical_datapath = lr_uuid, .__match = "ip4.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", .external_ids = stage_hint(lrp_uuid)) :- - &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, + &RouterPort(.lrp = &nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, .force_lb_snat = false, ._uuid = lr_uuid}, @@ -5097,7 +5097,7 @@ Flow(.logical_datapath = lr_uuid, .__match = "ip6.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", .external_ids = stage_hint(lrp_uuid)) :- - &RouterPort(.lrp = nb::Logical_Router_Port{._uuid = lrp_uuid}, + &RouterPort(.lrp = &nb::Logical_Router_Port{._uuid = lrp_uuid}, .router = &Router{.snat_ips = snat_ips, .force_lb_snat = false, ._uuid = lr_uuid}, @@ -6199,7 +6199,7 @@ function copy_ra_to_sb(port: RouterPort, address_mode: string): Map X-Patchwork-Id: 1475333 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxlw5NvGz9sPf for ; Fri, 7 May 2021 14:09:16 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 14E0A41993; Fri, 7 May 2021 04:09:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CMg38iHQemR3; Fri, 7 May 2021 04:09:11 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id D4EED404E7; Fri, 7 May 2021 04:08:59 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C5D09C0011; Fri, 7 May 2021 04:08:59 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 32D7FC0022 for ; Fri, 7 May 2021 04:08:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 3B208404B6 for ; Fri, 7 May 2021 04:07:56 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id eHptKl-rs4t3 for ; Fri, 7 May 2021 04:07:53 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id CDB754053E for ; Fri, 7 May 2021 04:07:49 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 1411AC0006; Fri, 7 May 2021 04:07:46 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:57 -0700 Message-Id: <20210507040659.26830-26-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 25/27] ovn-northd-ddlog: Intern nb::Logical_Switch_Port. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk Use the `--intern-table` switch to intern `Logical_Switch_Port` records, so that they can be copied and compared efficiently by pointer. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/helpers.dl | 2 +- northd/lrouter.dl | 4 ++-- northd/lswitch.dl | 28 ++++++++++++++-------------- northd/multicast.dl | 6 +++--- northd/ovn-nb.dlopts | 1 + northd/ovn_northd.dl | 38 +++++++++++++++++++------------------- 6 files changed, 40 insertions(+), 39 deletions(-) diff --git a/northd/helpers.dl b/northd/helpers.dl index 820e37bb3072..757532e46c0e 100644 --- a/northd/helpers.dl +++ b/northd/helpers.dl @@ -23,7 +23,7 @@ output relation Warning[string] /* Switch-to-router logical port connections */ relation SwitchRouterPeer(lsp: uuid, lsp_name: string, lrp: uuid) SwitchRouterPeer(lsp, lsp_name, lrp) :- - nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = "router", .options = options), + &nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = "router", .options = options), Some{var router_port} = options.get("router-port"), &nb::Logical_Router_Port(.name = router_port, ._uuid = lrp). diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 3b5047c3ec01..a85e12d1b3df 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -92,7 +92,7 @@ FirstHopLogicalRouter(lrouter, lswitch) :- relation LogicalSwitchRouterPort(lsp: uuid, lsp_router_port: string, ls: uuid) LogicalSwitchRouterPort(lsp, lsp_router_port, ls) :- LogicalSwitchPort(lsp, ls), - nb::Logical_Switch_Port(._uuid = lsp, .__type = "router", .options = options), + &nb::Logical_Switch_Port(._uuid = lsp, .__type = "router", .options = options), Some{var lsp_router_port} = options.get("router-port"). /* @@ -359,7 +359,7 @@ typedef LBForceSNAT = NoForceSNAT | ForceSNAT | SkipSNAT -function snat_for_lb(lr_options: Map, lb: Ref): LBForceSNAT { +function snat_for_lb(lr_options: Map, lb: Intern): LBForceSNAT { if (lb.options.get_bool_def("skip_snat", false)) { return SkipSNAT }; diff --git a/northd/lswitch.dl b/northd/lswitch.dl index cc0777f743c1..1004427b725c 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -22,7 +22,7 @@ import helpers import ipam import vec -function is_enabled(lsp: nb::Logical_Switch_Port): bool { is_enabled(lsp.enabled) } +function is_enabled(lsp: Intern): bool { is_enabled(lsp.enabled) } function is_enabled(sp: SwitchPort): bool { sp.lsp.is_enabled() } function is_enabled(sp: Intern): bool { sp.lsp.is_enabled() } @@ -33,7 +33,7 @@ SwitchRouterPeerRef(lsp, Some{rport}) :- rport in &RouterPort(.lrp = &nb::Logical_Router_Port{._uuid = lrp}). SwitchRouterPeerRef(lsp, None) :- - nb::Logical_Switch_Port(._uuid = lsp), + &nb::Logical_Switch_Port(._uuid = lsp), not SwitchRouterPeer(lsp, _, _). /* LogicalSwitchPortCandidate. @@ -50,7 +50,7 @@ Warning[message] :- LogicalSwitchPortCandidate(lsp_uuid, ls_uuid), var lss = ls_uuid.group_by(lsp_uuid).to_set(), lss.size() > 1, - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), var message = "Bad configuration: logical switch port ${lsp.name} belongs " "to more than one logical switch". @@ -66,7 +66,7 @@ LogicalSwitchPort(lsp_uuid, ls_uuid) :- relation LogicalSwitchPortWithUnknownAddress(ls: uuid, lsp: uuid) LogicalSwitchPortWithUnknownAddress(ls_uuid, lsp_uuid) :- LogicalSwitchPort(lsp_uuid, ls_uuid), - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), lsp.is_enabled() and lsp.addresses.contains("unknown"). relation LogicalSwitchHasUnknownPorts(ls: uuid, has_unknown: bool) @@ -81,7 +81,7 @@ relation PortStaticAddresses(lsport: uuid, ip4addrs: Set, ip6addrs: Set< PortStaticAddresses(.lsport = port_uuid, .ip4addrs = ip4_addrs.union(), .ip6addrs = ip6_addrs.union()) :- - nb::Logical_Switch_Port(._uuid = port_uuid, .addresses = addresses), + &nb::Logical_Switch_Port(._uuid = port_uuid, .addresses = addresses), var address = FlatMap(if (addresses.is_empty()) { set_singleton("") } else { addresses }), (var ip4addrs, var ip6addrs) = if (not is_dynamic_lsp_address(address)) { split_addresses(address) @@ -133,7 +133,7 @@ relation LogicalSwitchLocalnetPort0(ls_uuid: uuid, lsp: (uuid, string)) LogicalSwitchLocalnetPort0(ls_uuid, (lsp_uuid, lsp.name)) :- ls in nb::Logical_Switch(._uuid = ls_uuid), var lsp_uuid = FlatMap(ls.ports), - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), lsp.__type == "localnet". relation LogicalSwitchLocalnetPorts(ls_uuid: uuid, localnet_ports: Vec<(uuid, string)>) @@ -173,7 +173,7 @@ relation LogicalSwitchHasNonRouterPort0(ls: uuid) LogicalSwitchHasNonRouterPort0(ls_uuid) :- ls in nb::Logical_Switch(._uuid = ls_uuid), var lsp_uuid = FlatMap(ls.ports), - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), lsp.__type != "router". relation LogicalSwitchHasNonRouterPort(ls: uuid, has_non_router_port: bool) @@ -512,9 +512,9 @@ relation &SwitchACL(sw: Intern, function oVN_FEATURE_PORT_UP_NOTIF(): string { "port-up-notif" } relation SwitchPortUp0(lsp: uuid) SwitchPortUp0(lsp) :- - nb::Logical_Switch_Port(._uuid = lsp, .__type = "router"). + &nb::Logical_Switch_Port(._uuid = lsp, .__type = "router"). SwitchPortUp0(lsp) :- - nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = __type), + &nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = __type), sb::Port_Binding(.logical_port = lsp_name, .up = up, .chassis = Some{chassis_uuid}), sb::Chassis(._uuid = chassis_uuid, .other_config = other_config), if (other_config.get_bool_def(oVN_FEATURE_PORT_UP_NOTIF(), false)) { @@ -525,11 +525,11 @@ SwitchPortUp0(lsp) :- relation SwitchPortUp(lsp: uuid, up: bool) SwitchPortUp(lsp, true) :- SwitchPortUp0(lsp). -SwitchPortUp(lsp, false) :- nb::Logical_Switch_Port(._uuid = lsp), not SwitchPortUp0(lsp). +SwitchPortUp(lsp, false) :- &nb::Logical_Switch_Port(._uuid = lsp), not SwitchPortUp0(lsp). relation SwitchPortHAChassisGroup0(lsp_uuid: uuid, hac_group_uuid: uuid) SwitchPortHAChassisGroup0(lsp_uuid, ha_chassis_group_uuid(ls_uuid)) :- - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), lsp.__type == "external", Some{var hac_group_uuid} = lsp.ha_chassis_group, ha_chassis_group in nb::HA_Chassis_Group(._uuid = hac_group_uuid), @@ -542,7 +542,7 @@ relation SwitchPortHAChassisGroup(lsp_uuid: uuid, hac_group_uuid: Option) SwitchPortHAChassisGroup(lsp_uuid, Some{hac_group_uuid}) :- SwitchPortHAChassisGroup0(lsp_uuid, hac_group_uuid). SwitchPortHAChassisGroup(lsp_uuid, None) :- - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), + lsp in &nb::Logical_Switch_Port(._uuid = lsp_uuid), not SwitchPortHAChassisGroup0(lsp_uuid, _). /* SwitchPort relation collects all attributes of a logical switch port @@ -558,7 +558,7 @@ SwitchPortHAChassisGroup(lsp_uuid, None) :- * - 'hac_group_uuid' - uuid of sb::HA_Chassis_Group, only for "external" ports */ typedef SwitchPort = SwitchPort { - lsp: nb::Logical_Switch_Port, + lsp: Intern, json_name: string, sw: Intern, peer: Option>, @@ -602,7 +602,7 @@ SwitchPort[SwitchPort{ .mcast_cfg = mcast_cfg, .hac_group_uuid = hac_group_uuid }.intern()] :- - nb::Logical_Switch_Port[lsp], + lsp in &nb::Logical_Switch_Port(), LogicalSwitchPort(lsp._uuid, lswitch_uuid), sw in &Switch(._uuid = lswitch_uuid, .other_config = other_config, diff --git a/northd/multicast.dl b/northd/multicast.dl index bd9bc9b46f61..dfd58f4770bd 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -96,7 +96,7 @@ typedef McastPortCfg = McastPortCfg { relation McastPortCfg[Intern] McastPortCfg[McastPortCfg{lsp_uuid, false, flood, flood_reports}.intern()] :- - nb::Logical_Switch_Port(._uuid = lsp_uuid, .options = options), + &nb::Logical_Switch_Port(._uuid = lsp_uuid, .options = options), var flood = options.get_bool_def("mcast_flood", false), var flood_reports = options.get_bool_def("mcast_flood_reports", false). @@ -195,7 +195,7 @@ IgmpSwitchGroupPort(address, switch, lsp_uuid) :- var pb_port_uuid = FlatMap(pb_ports), sb::Port_Binding(._uuid = pb_port_uuid, .logical_port = lsp_name), &SwitchPort( - .lsp = nb::Logical_Switch_Port{._uuid = lsp_uuid, .name = lsp_name}, + .lsp = &nb::Logical_Switch_Port{._uuid = lsp_uuid, .name = lsp_name}, .sw = switch). IgmpSwitchGroupPort(address, switch, localnet_port.0) :- IgmpSwitchGroupPort(address, switch, _), @@ -235,7 +235,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :- None -> true }, var flood_port = FlatMap(sw_flood_ports), - &SwitchPort(.lsp = nb::Logical_Switch_Port{._uuid = flood_port}, + &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = flood_port}, .peer = Some{rtr_port}). /* Aggregated IGMP group for routers: merges all IgmpRouterGroupPort for diff --git a/northd/ovn-nb.dlopts b/northd/ovn-nb.dlopts index c1ceb4f1496a..402a44636ab9 100644 --- a/northd/ovn-nb.dlopts +++ b/northd/ovn-nb.dlopts @@ -22,3 +22,4 @@ --intern-table NAT --intern-table Address_Set --intern-table Logical_Router_Port +--intern-table Logical_Switch_Port diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index f7744a1dae75..9536b38816f5 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -501,7 +501,7 @@ RefChassis(lr_uuid, chassis_uuid) :- ReachableLogicalRouter(lr_uuid, lr2_uuid), FirstHopLogicalRouter(lr2_uuid, ls_uuid), LogicalSwitchPort(lsp_uuid, ls_uuid), - nb::Logical_Switch_Port(._uuid = lsp_uuid, .name = lsp_name), + &nb::Logical_Switch_Port(._uuid = lsp_uuid, .name = lsp_name), sb::Port_Binding(.logical_port = lsp_name, .chassis = chassis_uuids), Some{var chassis_uuid} = chassis_uuids. relation RefChassisSet0(lr_uuid: uuid, chassis_uuids: Set) @@ -725,7 +725,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip4addrs.union()) :- // avoid name collisions with user-defined Address_Sets not &nb::Address_Set(.name = as_name), PortStaticAddresses(.lsport = port_uuid, .ip4addrs = stat), - SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, + SwitchPortNewDynamicAddress(&SwitchPort{.lsp = &nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), var dynamic = match (dyn_addr) { None -> set_empty(), @@ -750,7 +750,7 @@ sb::Out_Address_Set(hash128(as_name), as_name, pg_ip6addrs.union()) :- // avoid name collisions with user-defined Address_Sets not &nb::Address_Set(.name = as_name), PortStaticAddresses(.lsport = port_uuid, .ip6addrs = stat), - SwitchPortNewDynamicAddress(&SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = port_uuid}}, + SwitchPortNewDynamicAddress(&SwitchPort{.lsp = &nb::Logical_Switch_Port{._uuid = port_uuid}}, dyn_addr), var dynamic = match (dyn_addr) { None -> set_empty(), @@ -789,8 +789,8 @@ PortGroupPort(pg_uuid, pg_name, port) :- sb::Out_Port_Group(._uuid = hash128(sb_name), .name = sb_name, .ports = port_names) :- PortGroupPort(.pg_uuid = _uuid, .pg_name = nb_name, .port = port_uuid), - &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{._uuid = port_uuid, - .name = port_name}, + &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{._uuid = port_uuid, + .name = port_name}, .sw = &Switch{._uuid = ls_uuid}), TunKeyAllocation(.datapath = ls_uuid, .tunkey = tunkey), var sb_name = "${tunkey}_${nb_name}", @@ -1846,7 +1846,7 @@ for (&Switch(._uuid =ls_uuid)) { * send all IP packets through the conntrack action, which handles * defragmentation, in order to match L4 headers. */ -for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, +for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "router"}, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) { /* Can't use ct() for router ports. Consider the @@ -1875,7 +1875,7 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, .external_ids = stage_hint(lsp._uuid)) } -for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "localnet"}, +for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "localnet"}, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) { Flow(.logical_datapath = ls_uuid, @@ -3224,7 +3224,7 @@ for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name) .external_ids = stage_hint(lsp._uuid)) } -function lsp_is_up(lsp: nb::Logical_Switch_Port): bool = { +function lsp_is_up(lsp: Intern): bool = { lsp.up == Some{true} } @@ -3245,12 +3245,12 @@ function lsp_is_up(lsp: nb::Logical_Switch_Port): bool = { "(arp.op == 2 && arp.spa == ${virtual_ip}))", .actions = "bind_vport(${sp.json_name}, inport); next;", .external_ids = stage_hint(lsp._uuid)) :- - sp in &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "virtual"}), + sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "virtual"}), Some{var virtual_ip} = lsp.options.get("virtual-ip"), Some{var virtual_parents} = lsp.options.get("virtual-parents"), Some{var ip} = ip_parse(virtual_ip), var vparent = FlatMap(string_split(virtual_parents, ",")), - vp in &SwitchPort(.lsp = nb::Logical_Switch_Port{.name = vparent}), + vp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{.name = vparent}), vp.sw == sp.sw. /* @@ -3379,7 +3379,7 @@ Flow(.logical_datapath = sp.sw._uuid, var lbvipbackend = FlatMap(lbvip.backends), Some{var svc_monitor} = lbvipbackend.svc_monitor, sp in &SwitchPort( - .lsp = nb::Logical_Switch_Port{.name = svc_monitor.port_name}), + .lsp = &nb::Logical_Switch_Port{.name = svc_monitor.port_name}), var svc_mon_src_ip = svc_monitor.src_ip, SvcMonitorMac(svc_monitor_mac). @@ -3571,7 +3571,7 @@ for (lsp in &SwitchPort Some{var dhcpv4_options_uuid} = lsp.lsp.dhcpv4_options in { for (dhcpv4_options in &nb::DHCP_Options(._uuid = dhcpv4_options_uuid)) { - for (SwitchPortIPv4Address(.port = &SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { + for (SwitchPortIPv4Address(.port = &SwitchPort{.lsp = &nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { Some{(var options_action, var response_action, var ipv4_addr_match)} = build_dhcpv4_action(json_key, dhcpv4_options, addr.addr) in { @@ -3628,7 +3628,7 @@ for (lsp in &SwitchPort Some{var dhcpv6_options_uuid} = lsp.lsp.dhcpv6_options in { for (dhcpv6_options in &nb::DHCP_Options(._uuid = dhcpv6_options_uuid)) { - for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { + for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = &nb::Logical_Switch_Port{._uuid = lsp.lsp._uuid}}, .ea = ea, .addr = addr)) { Some{(var options_action, var response_action)} = build_dhcpv6_action(json_key, dhcpv6_options, addr.addr) in { @@ -4287,7 +4287,7 @@ Flow(.logical_datapath = ls_uuid, .actions = "put_fdb(inport, eth.src); next;", .external_ids = stage_hint(lsp_uuid)) :- LogicalSwitchPortWithUnknownAddress(ls_uuid, lsp_uuid), - sp in &SwitchPort(.lsp = nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = ""}, + sp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = ""}, .ps_addresses = vec_empty()). Flow(.logical_datapath = ls_uuid, @@ -6969,7 +6969,7 @@ Flow(.logical_datapath = peer.router._uuid, "${rEG_NEXT_HOP()} == ${virtual_ip}", .actions = "eth.dst = 00:00:00:00:00:00; next;", .external_ids = stage_hint(sp.lsp._uuid)) :- - sp in &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "virtual"}), + sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "virtual"}), Some{var virtual_ip_s} = lsp.options.get("virtual-ip"), Some{var virtual_parents} = lsp.options.get("virtual-parents"), Some{var virtual_ip} = ip_parse(virtual_ip_s), @@ -6984,14 +6984,14 @@ Flow(.logical_datapath = peer.router._uuid, "${rEG_NEXT_HOP()} == ${virtual_ip}", .actions = "eth.dst = ${address.ea}; next;", .external_ids = stage_hint(sp.lsp._uuid)) :- - sp in &SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "virtual"}), + sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "virtual"}), Some{var virtual_ip_s} = lsp.options.get("virtual-ip"), Some{var virtual_parents} = lsp.options.get("virtual-parents"), Some{var virtual_ip} = ip_parse(virtual_ip_s), pb in sb::Port_Binding(.logical_port = sp.lsp.name), not (is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None), Some{var virtual_parent} = pb.virtual_parent, - vp in &SwitchPort(.lsp = nb::Logical_Switch_Port{.name = virtual_parent}), + vp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{.name = virtual_parent}), var address = FlatMap(vp.static_addresses), sp2 in &SwitchPort(.sw = sp.sw, .peer = Some{peer}), Some{_} = find_lrp_member_ip(peer.networks, IPv4{virtual_ip}). @@ -7651,7 +7651,7 @@ SwitchPortReservedTags(parent_name, tags) :- var tags = tag.group_by(parent_name).to_set(). SwitchPortReservedTags(parent_name, set_empty()) :- - nb::Logical_Switch_Port(.name = parent_name), + &nb::Logical_Switch_Port(.name = parent_name), not SwitchPortReservedTag(.parent_name = parent_name). /* Allocate tags for ports that require dynamically allocated tags and do not @@ -7713,7 +7713,7 @@ sb::Out_IP_Multicast(._uuid = cfg.datapath, relation PortExists(name: string) -PortExists(name) :- nb::Logical_Switch_Port(.name = name). +PortExists(name) :- &nb::Logical_Switch_Port(.name = name). PortExists(name) :- &nb::Logical_Router_Port(.name = name). sb::Out_Load_Balancer(._uuid = lb._uuid, From patchwork Fri May 7 04:06:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475339 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbxmP0H7dz9sPf for ; Fri, 7 May 2021 14:09:40 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id D6D874309E; Fri, 7 May 2021 04:09:38 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0cqCUhjY3eCt; Fri, 7 May 2021 04:09:37 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 191BA41981; Fri, 7 May 2021 04:09:17 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D5352C000E; Fri, 7 May 2021 04:09:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 22086C0001 for ; Fri, 7 May 2021 04:09:16 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C289641505 for ; Fri, 7 May 2021 04:08:01 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tfWNmPUGoQ4A for ; Fri, 7 May 2021 04:07:56 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 9C3294054A for ; Fri, 7 May 2021 04:07:51 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id C2E78C0010; Fri, 7 May 2021 04:07:48 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:58 -0700 Message-Id: <20210507040659.26830-27-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Leonid Ryzhyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 26/27] ovn-northd-ddlog: Remove Router.static_routes. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Leonid Ryzhyk This is another instance of a performance bug when a change to a router object forces a cascade of changes to relations that reference the object. This time around the problem was caused by the `Router.static_routes` field, which is copied from `nb::Logical_Router`. Luckily, this field was only used in one rule and was easy to remove. Here is how we diagnosed the issue (this may be useful for posterity): - We started with a benchmark that executed several hundreds of similar transactions (in this case, these transactions were adding new router ports). We recorded execution of the benchmark in a DDlog command file (replay.txt) and added `timestamp;` commands after each transaction in the file. - Run `make NORTHD_CLI=1` to generate the ovn_northd_cli executable and use it to execute the command file: ``` ./ovn_northd_ddlog/target/release/ovn_northd_cli -w 1 < replay.txt > replay.dump ``` - Extract only the timestamps from replay.dump and plot differences between successive timestamps (i.e., individual transaction times). I use gnumeric. It would be nice to have some automation for this in the future. We observe that one of the transactions in the benchmark loop slows down linearly as the size of the network topology grows: https://gist.github.com/ryzhyk/16a5607b280ed9cd09b176d6816cb4f0 Clearly some of the rules in the program are getting more expensive as the number of ports goes up. Another interesting observation is that the size of the delta output at each iteration of the benchmark remains constant (the delta mostly consists of new network flows). This suggests that whatever extra work DDlog is doing at each iteration might be redundant. - To identify where the wasted work happens, we re-compile the program passing the `--output-internal-relations` flag to DDlog, which tells it to dump changes to all intermediate relations, not just output relation. We replay the trace again. We locate the expensive transaction in the log and compare its output from one of the first iterations vs one from the end of the log. We now see a whole bunch of intermediate relations that only had a few modified records in the first transaction versus hundreds in the second one. We further observe that all of these changes simply update the `static_routes` field (as explained above). - After removing the field, we observe that changes to intermediate relations no longer grow with the topology, and transaction timing increases much more slowly: https://gist.github.com/ryzhyk/d02784b9088d82f8549ea1b2ebdf095e Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index a85e12d1b3df..db24ee64636c 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -444,7 +444,6 @@ typedef Router = Router { /* Fields copied from nb::Logical_Router. */ _uuid: uuid, name: string, - static_routes: Set, policies: Set, enabled: Option, nat: Set, @@ -469,7 +468,6 @@ relation Router[Intern] Router[Router{ ._uuid = lr._uuid, .name = lr.name, - .static_routes = lr.static_routes, .policies = lr.policies, .enabled = lr.enabled, .nat = lr.nat, @@ -740,7 +738,8 @@ RouterStaticRoute_(.router = router, .nexthop = route.nexthop, .output_port = route.output_port, .ecmp_symmetric_reply = route.ecmp_symmetric_reply) :- - router in &Router(.static_routes = routes), + router in &Router(), + nb::Logical_Router(._uuid = router._uuid, .static_routes = routes), var route_id = FlatMap(routes), route in &StaticRoute(.lrsr = nb::Logical_Router_Static_Route{._uuid = route_id}). From patchwork Fri May 7 04:06:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1475340 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fbxmw1FX5z9sPf for ; Fri, 7 May 2021 14:10:08 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 11AE76F628; Fri, 7 May 2021 04:10:06 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id koS41bAVtLID; Fri, 7 May 2021 04:10:04 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id D83C86F6C4; Fri, 7 May 2021 04:09:22 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B3701C000E; Fri, 7 May 2021 04:09:22 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 18ED3C000E for ; Fri, 7 May 2021 04:09:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 83ED740F02 for ; Fri, 7 May 2021 04:08:03 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id swW0BXnKAMUv for ; Fri, 7 May 2021 04:07:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp4.osuosl.org (Postfix) with ESMTPS id 5FECD404AD for ; Fri, 7 May 2021 04:07:53 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 886D0C0007; Fri, 7 May 2021 04:07:50 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Thu, 6 May 2021 21:06:59 -0700 Message-Id: <20210507040659.26830-28-blp@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210507040659.26830-1-blp@ovn.org> References: <20210507040659.26830-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn v3 27/27] tutorial: Add benchmarking test script to run within sandbox. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This is originally from Numan Siddique. I have adapted it a bit to run faster by using the ovn-nbctl and ovn-sbctl daemons and combining multiple calls into just one. I'm uncertain whether to actually commit this; I need a sign-off from Numan to do so. Signed-off-by: Ben Pfaff CC: Numan Siddique --- tutorial/automake.mk | 3 +- tutorial/northd_ddlog_test.sh | 81 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100755 tutorial/northd_ddlog_test.sh diff --git a/tutorial/automake.mk b/tutorial/automake.mk index 13b3bee055c9..f2571c2cfd98 100644 --- a/tutorial/automake.mk +++ b/tutorial/automake.mk @@ -6,7 +6,8 @@ EXTRA_DIST += \ tutorial/t-stage2 \ tutorial/t-stage3 \ tutorial/t-stage4 \ - tutorial/ovn-setup.sh + tutorial/ovn-setup.sh \ + tutorial/northd_ddlog_test.sh sandbox: all cd $(srcdir)/tutorial && MAKE=$(MAKE) HAVE_OPENSSL=$(HAVE_OPENSSL) \ ./ovs-sandbox -b $(abs_builddir) --ovs-src $(ovs_srcdir) --ovs-build $(ovs_builddir) $(SANDBOXFLAGS) diff --git a/tutorial/northd_ddlog_test.sh b/tutorial/northd_ddlog_test.sh new file mode 100755 index 000000000000..57e45d96228f --- /dev/null +++ b/tutorial/northd_ddlog_test.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +ddlog_running () { + test -e sandbox/ovn-north-ddlog.pid +} + +rm -f sandbox/profile-[0-9]*.txt +if ddlog_running; then + ovs-appctl -t ovn-northd-ddlog enable-cpu-profiling +fi + +export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach) +export OVN_SB_DAEMON=$(ovn-sbctl --pidfile --detach) +trap 'kill $(cat $OVN_RUNDIR/ovn-nbctl.pid) $(cat $OVN_RUNDIR/ovn-sbctl.pid)' 0 + +ovn-nbctl set NB_Global . options:northd_probe_interval=180000 + +ovn-nbctl pg-add portGroupDefDeny +ovn-nbctl pg-add portGroupMultiDefDeny +ovn-nbctl lr-add cluster_router + +step () { + lswitch_name=lswitch_17.${i}.0.0/16 + ext_switch=ext_ls_2.${i}.0.0/16 + ext_lrouter=ext_lr_2.${i}.0.0/16 + j=2 + port_name=lp_17.${i}.0.${j} + port_ip=17.${i}.0.${j} + np=networkPolicy-$i-$j + ns=nameSpace-$i-$j + mg=mcastPortGroup_$ns + ovn-sbctl chassis-add ch$i geneve 128.0.0.$i + ovn-nbctl --wait=sb \ + ls-add ${lswitch_name} -- \ + lrp-add cluster_router lr-$lswitch_name 00:00:00:00:ff:$i 17.${i}.0.254/16 -- \ + lsp-add $lswitch_name $lswitch_name-lr -- \ + lsp-set-type $lswitch_name-lr router -- \ + lsp-set-addresses $lswitch_name-lr router -- \ + lsp-set-options $lswitch_name-lr router-port=lr-$lswitch_name -- \ + ls-add $ext_switch -- \ + lr-add $ext_lrouter -- \ + lrp-add $ext_lrouter extlr-$lswitch_name 00:00:00:10:af:$i 2.${i}.0.254/16 -- \ + lsp-add $ext_switch $ext_switch-lr_2.$i -- \ + lsp-set-type $ext_switch-lr_2.$i router -- \ + lsp-set-addresses $ext_switch-lr_2.$i router -- \ + lsp-set-options $ext_switch-lr_2.$i router-port=extlr-$lswitch_name -- \ + lr-nat-add $ext_lrouter snat 2.${i}.0.100 17.${i}.0.0/16 -- \ + lr-route-add $ext_lrouter 17.${i}.1.0/16 20.0.0.2 -- \ + --policy="src-ip" lr-route-add $ext_lrouter 192.168.2.0/24 20.0.0.3 -- \ + --policy="src-ip" lr-route-add cluster_router 17.${i}.1.0/16 20.0.0.4 -- \ + set logical_router $ext_lrouter options:chassis=ch$i -- \ + lsp-add ${lswitch_name} ${port_name} -- \ + lsp-set-addresses ${port_name} "dynamic ${port_ip}" -- \ + --id=@lsp get logical_switch_port ${port_name} -- \ + add port_group portGroupDefDeny ports @lsp -- \ + add port_group portGroupMultiDefDeny ports @lsp -- \ + pg-add $np $port_name -- \ + create Address_Set name=${np}_ingress_as addresses=$port_ip -- \ + create Address_Set name=${np}_egress_as addresses=$port_ip -- \ + acl-add $np from-lport 1010 "inport == @$np && ip4.src == ${np}_ingress_as" allow -- \ + acl-add $np from-lport 1009 "inport == @$np && ip4" allow-related -- \ + acl-add $np to-lport 1010 "outport == @$np && ip4.dst == ${np}_egress_as" allow -- \ + acl-add $np to-lport 1009 "outport == @$np && ip4" allow -- \ + create Address_Set name=$ns addresses=$port_ip -- \ + pg-add $mg $port_name -- \ + acl-add $mg from-lport 1012 "inport == @${mg} && ip4.mcast" allow -- \ + acl-add $mg to-lport 1012 "outport == @${mg} && ip4.mcast" allow >/dev/null + ovn-sbctl lsp-bind $port_name ch$i + + if ddlog_running; then + ovs-appctl -t ovn-northd-ddlog profile > sandbox/profile-$i.txt + fi +} + +rm -f timings +i=1 +while [ $i -lt 255 ] +do + printf "step $i: "; TIMEFORMAT=%R; time step + i=$((i+1)) +done