Re: [ovs-dev] [PATCH ovn v5 0/6] northd: Introduce incremental processing framework

2021-11-19 Thread Mark Gray
Thanks Han!

On Wed 17 Nov 2021, 06:58 Han Zhou,  wrote:

>
>
> On Tue, Nov 9, 2021 at 11:36 AM Mark Gray  wrote:
> >
> > Add the 'inc-proc-eng' framework to northd. This does *not*
> > add any incremental processing at this stage but provides the
> > framework to do so. Even in this base configuration, we see an
> > advantage as northd no longer processes the databases if it has
> > been woken only to handle, for example, a unixctl command. This
> > can be seen below
> >
> > $ ovn-appctl -t ovn-northd stopwatch/reset
> > $ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show
> >/dev/null; done
> > $ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
> > Statistics for 'ovnnb_db_run'
> >   Total samples: 0
> >   Maximum: 0 msec
> >   Minimum: 0 msec
> >   95th percentile: 0.00 msec
> >   Short term average: 0.00 msec
> >   Long term average: 0.00 msec
> >
> > Hopefully this starting point will allow others to discuss or contribute
> > changes to incrementally process some aspects of northd. We an also
> > decide if it is worth progressing with this in general.
> >
> > Thanks,
> >
> > v2: Rebase
> > v3: Fix compile error in 2/7 picked up by 0-day robot
> > v4: Rework based on Han's comments and rebase
> > v5: Rebase and address Han's comments
> >
> > Mark Gray (6):
> >   northd: Introduce incremental processing for northd
> >   northd: Add n_nat_entries field to 'struct ovn_datapath'
> >   northd: Introduce struct northd_data
> >   northd: Call build_mcast_groups() from build_lflows()
> >   northd: Add lflow node
> >   northd: Do not calculate database sequence numbers incrementally
> >
> >  lib/inc-proc-eng.h   |  17 +
> >  northd/automake.mk   |   6 +
> >  northd/en-lflow.c|  76 
> >  northd/en-lflow.h|  16 +
> >  northd/en-northd.c   | 130 ++
> >  northd/en-northd.h   |  17 +
> >  northd/inc-proc-northd.c | 287 +
> >  northd/inc-proc-northd.h |  16 +
> >  northd/northd.c  | 850 ---
> >  northd/northd.h  |  88 +++-
> >  northd/ovn-northd.c  | 360 +++--
> >  11 files changed, 1313 insertions(+), 550 deletions(-)
> >  create mode 100644 northd/en-lflow.c
> >  create mode 100644 northd/en-lflow.h
> >  create mode 100644 northd/en-northd.c
> >  create mode 100644 northd/en-northd.h
> >  create mode 100644 northd/inc-proc-northd.c
> >  create mode 100644 northd/inc-proc-northd.h
> >
> > --
>
> Thanks Mark and Numan! I applied the series to the main branch.
>
> Han
> > 2.17.1
> >
> >
> > --
> > This email has been checked for viruses by Avast antivirus software.
> > https://www.avast.com/antivirus
> >
>
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v3] ovsdb-server: Log database transactions for user requested tables.

2021-11-16 Thread Mark Gray
On Tue 16 Nov 2021, 14:34 Dumitru Ceara,  wrote:

> Add a new command, 'ovsdb-server/tlog-set DB:TABLE on|off', which
> allows the user to enable/disable transaction logging for specific
> databases and tables.
>
> By default, logging is disabled.  Once enabled, logs are generated
> with level INFO and are also rate limited.
>
> If used with care, this command can be useful in analyzing production
> deployment performance issues, allowing the user to pin point
> bottlenecks without the need to enable wider debug logs, e.g., jsonrpc.
>
> A command to inspect the logging state is also added:
> 'ovsdb-server/tlog-list'.
>
> Signed-off-by: Dumitru Ceara 
>

Hi Dumitru,

Thanks for addressing my comments satisfactorily. This looks good to me. No
need to add my Ack.

Mark

---
> A sample use case is an ovn-kubernetes scaled deployment in which
> we're interesting in reducing time to bring up PODs (represented by
> OVN logical switch ports).  In order to determine exactly where the
> bottleneck is when provisioning PODs (CMS/ovn-nbctl/client
> IDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when
> operations happen at various places in the stack.
>
> Without this patch the only option for tracking when transactions
> happen in the Northbound database is to enable jsonrpc debug logs in
> ovsdb-server.  This generates a rather large amount of data.
>
> Instead, now, users would be able to just enable logging for the
> Logical_Switch_Port table getting more relevant and precise
> information.
>
> V3:
> - rebased
> - addressed Mark Gray's comments
> V2:
> - rebased (fixed conflicts in NEWS).
> ---
>  NEWS|  4 ++
>  ovsdb/ovsdb-server.1.in |  7 
>  ovsdb/ovsdb-server.c| 86 +
>  ovsdb/row.c | 17 
>  ovsdb/row.h |  1 +
>  ovsdb/table.c   | 13 +++
>  ovsdb/table.h   |  4 ++
>  ovsdb/transaction.c | 49 +++
>  8 files changed, 181 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index 434ee570fb69..cc73f46f0135 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -16,6 +16,10 @@ Post-v2.16.0
> - ovs-dpctl and 'ovs-appctl dpctl/':
>   * New commands 'cache-get-size' and 'cache-set-size' that allows to
> get or configure linux kernel datapath cache sizes.
> +   - OVSDB:
> + * New unixctl command 'ovsdb-server/tlog-set DB:TABLE on|off".
> +   If turned on, ovsdb-server will log (at level INFO and rate
> limited)
> +   all operations that are committed to table TABLE in the DB
> database.
>
>
>  v2.16.0 - 16 Aug 2021
> diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in
> index dac0f02cb987..da7a6fd5d542 100644
> --- a/ovsdb/ovsdb-server.1.in
> +++ b/ovsdb/ovsdb-server.1.in
> @@ -273,6 +273,13 @@ again (with \fBovsdb\-server/add\-db\fR).
>  Outputs a list of the currently configured databases added either through
>  the command line or through the \fBovsdb\-server/add\-db\fR command.
>  .
> +.IP "\fBovsdb\-server/tlog\-set \fIdatabase\fR:\fItable\fR
> \fIon\fR|\fIoff\fR"
> +Enables or disables logging of all operations executed on the specified
> +database and table.  Logs are generated at INFO level and are rate
> limtied.
> +.
> +.IP "\fBovsdb\-server/tlog\-list"
> +Displays the logging state for all currently configured databases and
> tables.
> +.
>  .SS "Active-Backup Commands"
>  .PP
>  These commands query and update the role of \fBovsdb\-server\fR within
> diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
> index b34d97e29163..1a64363c7814 100644
> --- a/ovsdb/ovsdb-server.c
> +++ b/ovsdb/ovsdb-server.c
> @@ -115,6 +115,8 @@ static unixctl_cb_func ovsdb_server_list_remotes;
>  static unixctl_cb_func ovsdb_server_add_database;
>  static unixctl_cb_func ovsdb_server_remove_database;
>  static unixctl_cb_func ovsdb_server_list_databases;
> +static unixctl_cb_func ovsdb_server_tlog_set;
> +static unixctl_cb_func ovsdb_server_tlog_list;
>
>  static void read_db(struct server_config *, struct db *);
>  static struct ovsdb_error *open_db(struct server_config *,
> @@ -443,6 +445,10 @@ main(int argc, char *argv[])
>   ovsdb_server_remove_database,
> _config);
>  unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0,
>   ovsdb_server_list_databases, _dbs);
> +unixctl_command_register("ovsdb-server/tlog-set", "DB:TABLE on|off",
> + 2, 2, ovsdb_server_tlog_set, _dbs);
> +unixctl_command_register("ovsdb-server/tlog-list", NULL,
> + 0, 0, ovsdb_server_tlog_list, _dbs);
>  unixctl_command_register("ovsdb-server/perf-counters-show", "", 0, 0,
>   ovsdb_server_perf_counters_show, NULL);
>  unixctl_command_register("ovsdb-server/perf-counters-clear", "", 0, 0,
> @@ -1769,6 +1775,86 @@ ovsdb_server_list_databases(struct unixctl_conn
> *conn, int argc OVS_UNUSED,
>  ds_destroy();
>  }
>
> 

[ovs-dev] [PATCH ovn v5 5/6] northd: Add lflow node

2021-11-09 Thread Mark Gray
From: Mark Gray 

Add an additional node that initially does nothing. This serves as a
template for how to add a new node. This node is inserted after
the northd_node.

This node will be updated in a later commit to generate logical
flows for the SBDB.

Signed-off-by: Mark Gray 
---
 northd/automake.mk   |   2 +
 northd/en-lflow.c|  76 
 northd/en-lflow.h|  16 
 northd/en-northd.c   |  10 ---
 northd/inc-proc-northd.c |  11 ++-
 northd/inc-proc-northd.h |   2 -
 northd/northd.c  | 186 ---
 northd/northd.h  |  27 --
 northd/ovn-northd.c  |   1 -
 9 files changed, 214 insertions(+), 117 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h

diff --git a/northd/automake.mk b/northd/automake.mk
index f0c1fb11c83a..4862ec7b7ff3 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -6,6 +6,8 @@ northd_ovn_northd_SOURCES = \
northd/ovn-northd.c \
northd/en-northd.c \
northd/en-northd.h \
+   northd/en-lflow.c \
+   northd/en-lflow.h \
northd/inc-proc-northd.c \
northd/inc-proc-northd.h \
northd/ipam.c \
diff --git a/northd/en-lflow.c b/northd/en-lflow.c
new file mode 100644
index ..5bef35cf6117
--- /dev/null
+++ b/northd/en-lflow.c
@@ -0,0 +1,76 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-lflow.h"
+#include "en-northd.h"
+
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
+#include "timeval.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_lflow);
+
+void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+
+struct lflow_input lflow_input;
+
+struct northd_data *northd_data = engine_get_input_data("northd", node);
+
+lflow_input.sbrec_logical_flow_table =
+EN_OVSDB_GET(engine_get_input("SB_logical_flow", node));
+lflow_input.sbrec_multicast_group_table =
+EN_OVSDB_GET(engine_get_input("SB_multicast_group", node));
+lflow_input.sbrec_igmp_group_table =
+EN_OVSDB_GET(engine_get_input("SB_igmp_group", node));
+
+lflow_input.sbrec_mcast_group_by_name_dp =
+   engine_ovsdb_node_get_index(
+  engine_get_input("SB_multicast_group", node),
+ "sbrec_mcast_group_by_name");
+
+lflow_input.datapaths = _data->datapaths;
+lflow_input.ports = _data->ports;
+lflow_input.port_groups = _data->port_groups;
+lflow_input.meter_groups = _data->meter_groups;
+lflow_input.lbs = _data->lbs;
+lflow_input.bfd_connections = _data->bfd_connections;
+lflow_input.ovn_internal_version_changed =
+  northd_data->ovn_internal_version_changed;
+
+stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+build_lflows(_input, eng_ctx->ovnsb_idl_txn);
+stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+
+engine_set_node_state(node, EN_UPDATED);
+}
+void *en_lflow_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+return NULL;
+}
+
+void en_lflow_cleanup(void *data OVS_UNUSED)
+{
+}
diff --git a/northd/en-lflow.h b/northd/en-lflow.h
new file mode 100644
index ..0e4d522ff3fe
--- /dev/null
+++ b/northd/en-lflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_LFLOW_H
+#define EN_LFLOW_H 1
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "lib/inc-proc-eng.h"
+
+void en_lflow_run(struct engine_node *node, void *data);
+void *en_lflow_init(struct engine_node *node, struct engine_arg *arg);
+void en_lflow_cleanup(void *data);
+
+#endif /* EN_LFLOW_H */
diff --git a/northd/en-northd.c b/northd/en-northd.c
index adcc459a9d16..2fda3a9d219d 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -51,10 +51,6 @@ void en_northd_run(struct engine_node *node, void *data)
 engine_ovsdb_node_get_index(
 engine_get_input("SB_ha_chassis_group", node),
 "sbrec_ha_chassis_grp_by_name");
-input_data.sbrec_mcast_group_by_name_dp =
-

[ovs-dev] [PATCH ovn v5 3/6] northd: Introduce struct northd_data

2021-11-09 Thread Mark Gray
From: Mark Gray 

'struct northd_data' is used to hold the global state data for the
incremental processing node 'en_northd'. This structure will also hold
'struct northd_input' which will hold references to output data from
its input nodes. In particular, this will hold references to database tables
and indexes. In order to achieve this, we refactor in the following way:

* Introduce northd_init() which initializes this data.
* Introduce northd_destroy() which clears this data for a new iteration.
* Remove 'ovn_internal_version' from the context passed to northd
  as it can be determined within northd using ovn_get_internal_version.
* Remove 'use_parallel_build' from the context as it is read from DB as
  suggested by Han.
* Refactor northd.c to use 'struct northd_data' and 'struct northd_input'
  where applicable.

Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |   3 +
 northd/en-northd.c   | 107 ++-
 northd/inc-proc-northd.c |  42 ++-
 northd/inc-proc-northd.h |   6 +-
 northd/northd.c  | 632 ++-
 northd/northd.h  |  73 -
 northd/ovn-northd.c  |  87 ++
 7 files changed, 596 insertions(+), 354 deletions(-)

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index f89a40bd54ca..1823750c814c 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -72,6 +72,9 @@ struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
 struct ovsdb_idl_txn *ovnnb_idl_txn;
+
+struct ovsdb_idl_loop *ovnsb_idl_loop;
+
 void *client_ctx;
 };
 
diff --git a/northd/en-northd.c b/northd/en-northd.c
index d310fa4dd31f..f39dbd9da3e0 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -20,26 +20,123 @@
 
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
+#include "openvswitch/list.h" /* TODO This is needed for ovn-parallel-hmap.h.
+   * lib/ovn-parallel-hmap.h should be updated
+   * to include this dependency itself */
+#include "lib/ovn-parallel-hmap.h"
 #include "northd.h"
+#include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
 
-void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+void en_northd_run(struct engine_node *node, void *data)
 {
 const struct engine_context *eng_ctx = engine_get_context();
-struct northd_context *ctx = eng_ctx->client_ctx;
-ovn_db_run(ctx);
 
+struct northd_input input_data;
+
+northd_destroy(data);
+northd_init(data);
+
+input_data.sbrec_chassis_by_name =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_chassis", node),
+"sbrec_chassis_by_name");
+input_data.sbrec_chassis_by_hostname =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_chassis", node),
+"sbrec_chassis_by_hostname");
+input_data.sbrec_ha_chassis_grp_by_name =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_ha_chassis_group", node),
+"sbrec_ha_chassis_grp_by_name");
+input_data.sbrec_mcast_group_by_name_dp =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_multicast_group", node),
+"sbrec_mcast_group_by_name");
+input_data.sbrec_ip_mcast_by_dp =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_ip_multicast", node),
+"sbrec_ip_mcast_by_dp");
+
+input_data.nbrec_nb_global_table =
+EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
+input_data.nbrec_logical_switch =
+EN_OVSDB_GET(engine_get_input("NB_logical_switch", node));
+input_data.nbrec_logical_router =
+EN_OVSDB_GET(engine_get_input("NB_logical_router", node));
+input_data.nbrec_load_balancer_table =
+EN_OVSDB_GET(engine_get_input("NB_load_balancer", node));
+input_data.nbrec_port_group_table =
+EN_OVSDB_GET(engine_get_input("NB_port_group", node));
+input_data.nbrec_bfd_table =
+EN_OVSDB_GET(engine_get_input("NB_bfd", node));
+input_data.nbrec_address_set_table =
+EN_OVSDB_GET(engine_get_input("NB_address_set", node));
+input_data.nbrec_meter_table =
+EN_OVSDB_GET(engine_get_input("NB_meter", node));
+input_data.nbrec_acl_table =
+EN_OVSDB_GET(engine_get_input("NB_acl", node));
+
+input_data.sbrec_sb_global_table =
+EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
+input_data.sbrec_datapath_binding_table =
+EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node));
+input_data.sbrec_port_binding_table =
+EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
+

[ovs-dev] [PATCH ovn v5 6/6] northd: Do not calculate database sequence numbers incrementally

2021-11-09 Thread Mark Gray
From: Mark Gray 

In order to remove the IDL loop variable from the engine context,
we do not calculate the database sequence numbers incrementally.

Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  2 -
 northd/en-northd.c   |  3 +-
 northd/inc-proc-northd.c |  2 -
 northd/inc-proc-northd.h |  1 -
 northd/northd.c  | 80 +++--
 northd/northd.h  |  3 +-
 northd/ovn-northd.c  | 85 ++--
 7 files changed, 89 insertions(+), 87 deletions(-)

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 1823750c814c..6f3918ae7789 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -73,8 +73,6 @@ struct engine_context {
 struct ovsdb_idl_txn *ovnsb_idl_txn;
 struct ovsdb_idl_txn *ovnnb_idl_txn;
 
-struct ovsdb_idl_loop *ovnsb_idl_loop;
-
 void *client_ctx;
 };
 
diff --git a/northd/en-northd.c b/northd/en-northd.c
index 2fda3a9d219d..0523560f8da9 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -110,8 +110,7 @@ void en_northd_run(struct engine_node *node, void *data)
 
 northd_run(_data, data,
eng_ctx->ovnnb_idl_txn,
-   eng_ctx->ovnsb_idl_txn,
-   eng_ctx->ovnsb_idl_loop);
+   eng_ctx->ovnsb_idl_txn);
 engine_set_node_state(node, EN_UPDATED);
 
 }
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index d4c913883d9a..c7f49d59934d 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -248,7 +248,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
- struct ovsdb_idl_loop *ovnsb_idl_loop,
  bool recompute) {
 engine_set_force_recompute(recompute);
 engine_init_run();
@@ -256,7 +255,6 @@ void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
 struct engine_context eng_ctx = {
 .ovnnb_idl_txn = ovnnb_txn,
 .ovnsb_idl_txn = ovnsb_txn,
-.ovnsb_idl_loop = ovnsb_idl_loop,
 };
 
 engine_set_context(_ctx);
diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
index 4aeb387b7b0f..1300253791b6 100644
--- a/northd/inc-proc-northd.h
+++ b/northd/inc-proc-northd.h
@@ -10,7 +10,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb);
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
- struct ovsdb_idl_loop *ovnsb_idl_loop,
  bool recompute);
 void inc_proc_northd_cleanup(void);
 
diff --git a/northd/northd.c b/northd/northd.c
index dd543378463f..88be1775527f 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -14553,9 +14553,7 @@ ovnnb_db_run(struct northd_input *input_data,
  struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
  struct ovsdb_idl_index *sbrec_chassis_by_name,
- struct ovsdb_idl_index *sbrec_chassis_by_hostname,
- struct ovsdb_idl_loop *sb_loop,
- int64_t loop_start_time)
+ struct ovsdb_idl_index *sbrec_chassis_by_hostname)
 {
 if (!ovnsb_txn || !ovnnb_txn) {
 return;
@@ -14578,12 +14576,7 @@ ovnnb_db_run(struct northd_input *input_data,
 if (nb->ipsec != sb->ipsec) {
 sbrec_sb_global_set_ipsec(sb, nb->ipsec);
 }
-if (nb->nb_cfg != sb->nb_cfg) {
-sbrec_sb_global_set_nb_cfg(sb, nb->nb_cfg);
-nbrec_nb_global_set_nb_cfg_timestamp(nb, loop_start_time);
-}
 sbrec_sb_global_set_options(sb, >options);
-sb_loop->next_cfg = nb->nb_cfg;
 
 const char *mac_addr_prefix = set_mac_prefix(smap_get(>options,
   "mac_prefix"));
@@ -14884,68 +14877,12 @@ handle_port_binding_changes(struct northd_input 
*input_data,
 }
 }
 
-/* Updates the sb_cfg and hv_cfg columns in the northbound NB_Global table. */
-static void
-update_northbound_cfg(struct northd_input *input_data,
-  struct ovsdb_idl_loop *sb_loop,
-  int64_t loop_start_time)
-{
-/* Update northbound sb_cfg if appropriate. */
-const struct nbrec_nb_global *nbg = nbrec_nb_global_table_first(
-   input_data->nbrec_nb_global_table);
-int64_t sb_cfg = sb_loop->cur_cfg;
-if (nbg && sb_cfg && nbg->sb_cfg != sb_cfg) {
-nbrec_nb_global_set_sb_cfg(nbg, sb_cfg);
-nbrec_nb_global_set_sb_cfg_timestamp(nbg, loop_start_time);
-}
-
-/* Update northbound hv_cfg if appropriate. */
-if (nbg) {
-/* Find minimum nb_cfg among all chassis. */
-const struct sbrec_chassis_private *chassis_priv;
-int64_t hv_cfg = nbg->nb_cfg;
-in

[ovs-dev] [PATCH ovn v5 1/6] northd: Introduce incremental processing for northd

2021-11-09 Thread Mark Gray
From: Mark Gray 

Initial implementation adds a single node (northd). This single
node executes the northd processing pipeline but does not do so
incrementally.

In order to develop incremental processing for northd, the code
will be organised with a .c/.h file for each I-P node following
the naming convention en-.c/.h. These files will
contain definition of the node data, the main node processing
functions and change handlers (if any). The purpose of these nodes
will be coordination of the nodes work and implemention of the
relevant interfaces to plug into the I-P framework. The actual
work that will be executed by the node will be organised into
a companion file or files. Ideally this file will follow the
naming convention of the node: e.g. en-.c is
associated with .c.

Initial node topology sees the northd node dependent on all DB
nodes. This will evolve over time.

Co-authored-by: Numan Siddique 
Signed-off-by: Numan Siddique 
Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  16 +++
 northd/automake.mk   |   4 +
 northd/en-northd.c   |  45 +++
 northd/en-northd.h   |  17 +++
 northd/inc-proc-northd.c | 254 +++
 northd/inc-proc-northd.h |  15 +++
 northd/northd.c  |  16 ++-
 northd/northd.h  |  11 +-
 northd/ovn-northd.c  | 211 
 9 files changed, 498 insertions(+), 91 deletions(-)
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 36495fdf8a94..f89a40bd54ca 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -63,15 +63,22 @@
 #define ENGINE_MAX_INPUT 256
 #define ENGINE_MAX_OVSDB_INDEX 256
 
+#include 
+#include 
+
+#include "compiler.h"
+
 struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
+struct ovsdb_idl_txn *ovnnb_idl_txn;
 void *client_ctx;
 };
 
 /* Arguments to be passed to the engine at engine_init(). */
 struct engine_arg {
 struct ovsdb_idl *sb_idl;
+struct ovsdb_idl *nb_idl;
 struct ovsdb_idl *ovs_idl;
 };
 
@@ -344,6 +351,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_FUNC_SB(TBL_NAME) \
 ENGINE_FUNC_OVSDB(sb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN NB DB */
+#define ENGINE_FUNC_NB(TBL_NAME) \
+ENGINE_FUNC_OVSDB(nb, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -357,6 +369,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
 ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
 
+/* Macro to define an engine node which represents a table of OVN NB DB */
+#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
+ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
diff --git a/northd/automake.mk b/northd/automake.mk
index 35ad8c09d9ba..f0c1fb11c83a 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
northd/northd.c \
northd/northd.h \
northd/ovn-northd.c \
+   northd/en-northd.c \
+   northd/en-northd.h \
+   northd/inc-proc-northd.c \
+   northd/inc-proc-northd.h \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/en-northd.c b/northd/en-northd.c
new file mode 100644
index ..d310fa4dd31f
--- /dev/null
+++ b/northd/en-northd.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-northd.h"
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_northd);
+
+void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_context *ctx = eng_ctx->client_ctx;
+ovn_db_run(ctx);
+
+engine_set

[ovs-dev] [PATCH ovn v5 4/6] northd: Call build_mcast_groups() from build_lflows()

2021-11-09 Thread Mark Gray
From: Mark Gray 

As 'mcast_groups' and 'igmp_groups' need to be modified by
build_lflows(), we move build_mcast_groups() to build_flows(). This
is in preparation for a later commit which will create an lflow
node. If these structures form part of the input of the new lflow
we should not modify them as they would not form part of the mutable
state of that node.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c |  1 -
 northd/northd.c| 51 +-
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index f39dbd9da3e0..adcc459a9d16 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -138,5 +138,4 @@ void *en_northd_init(struct engine_node *node OVS_UNUSED,
 void en_northd_cleanup(void *data)
 {
 northd_destroy(data);
-free(data);
 }
diff --git a/northd/northd.c b/northd/northd.c
index 17b9d09a7887..1690d0d467a0 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -13404,12 +13404,23 @@ static ssize_t max_seen_lflow_size = 128;
 static bool needs_parallel_init = true;
 static bool reset_parallel = false;
 
+static void
+build_mcast_groups(struct northd_input *input_data,
+   struct hmap *datapaths, struct hmap *ports,
+   struct hmap *mcast_groups,
+   struct hmap *igmp_groups);
+
 /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database,
  * constructing their contents based on the OVN_NB database. */
 void build_lflows(struct northd_input *input_data,
   struct northd_data *data, struct ovsdb_idl_txn *ovnsb_txn)
 {
 struct hmap lflows;
+struct hmap mcast_groups;
+struct hmap igmp_groups;
+
+build_mcast_groups(input_data, >datapaths, >ports,
+   _groups, _groups);
 
 if (reset_parallel) {
 /* Parallel build was disabled before, we need to
@@ -13431,7 +13442,7 @@ void build_lflows(struct northd_input *input_data,
 }
 build_lswitch_and_lrouter_flows(>datapaths, >ports,
 >port_groups, ,
->mcast_groups, >igmp_groups,
+_groups, _groups,
 >meter_groups, >lbs,
 >bfd_connections);
 
@@ -13703,19 +13714,19 @@ void build_lflows(struct northd_input *input_data,
 
 struct multicast_group group = { .name = sbmc->name,
  .key = sbmc->tunnel_key };
-struct ovn_multicast *mc = ovn_multicast_find(>mcast_groups,
+struct ovn_multicast *mc = ovn_multicast_find(_groups,
   od, );
 if (mc) {
 ovn_multicast_update_sbrec(mc, sbmc);
-ovn_multicast_destroy(>mcast_groups, mc);
+ovn_multicast_destroy(_groups, mc);
 } else {
 sbrec_multicast_group_delete(sbmc);
 }
 }
 struct ovn_multicast *mc, *next_mc;
-HMAP_FOR_EACH_SAFE (mc, next_mc, hmap_node, >mcast_groups) {
+HMAP_FOR_EACH_SAFE (mc, next_mc, hmap_node, _groups) {
 if (!mc->datapath) {
-ovn_multicast_destroy(>mcast_groups, mc);
+ovn_multicast_destroy(_groups, mc);
 continue;
 }
 sbmc = sbrec_multicast_group_insert(ovnsb_txn);
@@ -13723,8 +13734,23 @@ void build_lflows(struct northd_input *input_data,
 sbrec_multicast_group_set_name(sbmc, mc->group->name);
 sbrec_multicast_group_set_tunnel_key(sbmc, mc->group->key);
 ovn_multicast_update_sbrec(mc, sbmc);
-ovn_multicast_destroy(>mcast_groups, mc);
+ovn_multicast_destroy(_groups, mc);
+}
+
+struct ovn_igmp_group *igmp_group, *next_igmp_group;
+
+HMAP_FOR_EACH_SAFE (igmp_group, next_igmp_group, hmap_node,
+_groups) {
+ovn_igmp_group_destroy(_groups, igmp_group);
 }
+
+struct ovn_port_group *pg, *next_pg;
+HMAP_FOR_EACH_SAFE (pg, next_pg, key_node, >port_groups) {
+ovn_port_group_destroy(>port_groups, pg);
+}
+
+hmap_destroy(_groups);
+hmap_destroy(_groups);
 }
 
 static void
@@ -14472,8 +14498,6 @@ northd_init(struct northd_data *data)
 hmap_init(>datapaths);
 hmap_init(>ports);
 hmap_init(>port_groups);
-hmap_init(>mcast_groups);
-hmap_init(>igmp_groups);
 shash_init(>meter_groups);
 hmap_init(>lbs);
 hmap_init(>bfd_connections);
@@ -14490,20 +14514,11 @@ northd_destroy(struct northd_data *data)
 }
 hmap_destroy(>lbs);
 
-struct ovn_igmp_group *igmp_group, *next_igmp_group;
-
-HMAP_FOR_EACH_SAFE (igmp_group, next_igmp_group, hmap_node,
->igmp_groups) {
-ovn_igmp_group_destroy(>igmp_groups, igmp_group);
-}
-
 struct ovn_port_group *pg, *next_pg;
   

[ovs-dev] [PATCH ovn v5 2/6] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-11-09 Thread Mark Gray
From: Mark Gray 

destroy_nat_entries() iterates over nat_entries using 'n_nat'
as the number of NAT entries from the NB database. This behaviour can be
incorrect as it assumes that there are 'n_nat' 'nat_entries'. 'struct
ovn_datapath' should maintain a count of 'nat_entries' in 'struct
ovn_datapath' rather than read the value from NBDB IDL to properly
account for the number of 'nat_entries'.

This issue becomes apparent when using destroy_nat_entries()
as part of an incremental processing loop:

Consider an example in which we have completed iteration x, and
started iteration x+1. If we add a NAT entry to NBDB between iteration x
and iteration x+1, od->nbr->n_nat will contain the updated value of
n_nat as the northbound record will have been updated. However, if
we do not (re)initialize the nat entries in od, od->n_nat_entries
could be equal to the previous value. This can cause destroy_nat_entries()
to loop over the wrong number of 'nat_entries' causing unexpected
behaviour.

Acked-by: Han Zhou 
Signed-off-by: Mark Gray 
---
 northd/northd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/northd/northd.c b/northd/northd.c
index c4bdfb649215..938dadf5563c 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -603,6 +603,8 @@ struct ovn_datapath {
 
 /* NAT entries configured on the router. */
 struct ovn_nat *nat_entries;
+size_t n_nat_entries;
+
 bool has_distributed_nat;
 
 /* Set of nat external ips on the router. */
@@ -787,6 +789,7 @@ init_nat_entries(struct ovn_datapath *od)
 od->has_distributed_nat = true;
 }
 }
+od->n_nat_entries = od->nbr->n_nat;
 }
 
 static void
@@ -800,7 +803,7 @@ destroy_nat_entries(struct ovn_datapath *od)
 destroy_lport_addresses(>dnat_force_snat_addrs);
 destroy_lport_addresses(>lb_force_snat_addrs);
 
-for (size_t i = 0; i < od->nbr->n_nat; i++) {
+for (size_t i = 0; i < od->n_nat_entries; i++) {
 destroy_lport_addresses(>nat_entries[i].ext_addrs);
 }
 }
-- 
2.17.1


-- 
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v5 0/6] northd: Introduce incremental processing framework

2021-11-09 Thread Mark Gray
Add the 'inc-proc-eng' framework to northd. This does *not*
add any incremental processing at this stage but provides the
framework to do so. Even in this base configuration, we see an
advantage as northd no longer processes the databases if it has
been woken only to handle, for example, a unixctl command. This
can be seen below

$ ovn-appctl -t ovn-northd stopwatch/reset
$ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show >/dev/null; done
$ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Statistics for 'ovnnb_db_run'
  Total samples: 0
  Maximum: 0 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 0.00 msec
  Long term average: 0.00 msec

Hopefully this starting point will allow others to discuss or contribute
changes to incrementally process some aspects of northd. We an also
decide if it is worth progressing with this in general.

Thanks,

v2: Rebase
v3: Fix compile error in 2/7 picked up by 0-day robot
v4: Rework based on Han's comments and rebase
v5: Rebase and address Han's comments

Mark Gray (6):
  northd: Introduce incremental processing for northd
  northd: Add n_nat_entries field to 'struct ovn_datapath'
  northd: Introduce struct northd_data
  northd: Call build_mcast_groups() from build_lflows()
  northd: Add lflow node
  northd: Do not calculate database sequence numbers incrementally

 lib/inc-proc-eng.h   |  17 +
 northd/automake.mk   |   6 +
 northd/en-lflow.c|  76 
 northd/en-lflow.h|  16 +
 northd/en-northd.c   | 130 ++
 northd/en-northd.h   |  17 +
 northd/inc-proc-northd.c | 287 +
 northd/inc-proc-northd.h |  16 +
 northd/northd.c  | 850 ---
 northd/northd.h  |  88 +++-
 northd/ovn-northd.c  | 360 +++--
 11 files changed, 1313 insertions(+), 550 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

-- 
2.17.1


-- 
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v4 4/6] northd: Introduce struct northd_data

2021-11-08 Thread Mark Gray
On Wed, Nov 3, 2021 at 11:37 PM Han Zhou  wrote:

> On Wed, Oct 27, 2021 at 10:24 AM Mark Gray  wrote:
> >
> > 'struct northd_data' is used to hold the global state data for the
> > incremental processing node 'en_northd'. This structure will also hold
> > 'struct northd_input' which will hold references to output data from
> > its input nodes. In particular, this will hold references to database
> tables
> > and indexes. In order to achieve this, we refactor in the following way:
>
> Thanks Mark for the revision. It does look more clear now with input data
> wrapped in northd_input. However, my suggestion was to move the inputs out
> of the northd_data completely (sorry if I wasn't clear on this).
>

You were clear on it. I just wasn't 100% sure how I should do it. However,
your description below has inspired me.


> The reason is, northd_data should contain only output data of en_northd,
> which is potentially going to be used as input data for other nodes that
> depend on en_northd. The other nodes depending on en_northd are supposed to
> access any data included in northd_data. If we put northd_input in the
> northd_data itself, those nodes may access them as well by mistake, and it
> is going to be hard to track the dependencies properly with the I-P engine.
> So my suggestion is just keep these two as independent structures, one for
> input and one for output. The northd_input will be used by en_northd's
> run() and handlers only. If another node depends on some common input in
> northd_input, they should declare the dependency in the I-P engine and get
> the data from their own input nodes.
>
> For northd_run(), it can have the signature like northd_run(northd_input,
> ..., north_output).
>

Yes makes sense.


>
> With convention of I-P in ovn-controller, we would name the struct
> northd_data ed_type_northd_data, to make it clear this is the output data
> maintained for the I-P engine node. I understand that you don't want
> anything related to I-P engine in the northd.h/c, so not following the
> naming convention is ok for me. I'd just remind that these data types are
>

Happy to change the names as you see fit. Let me know if you would like me
to.


> interfaces between different engine nodes, so be aware that it is less of
> an encapsulation but more like table definitions in a DB schema.
>
> The rest of the patch LGTM.
>
> Thanks,
> Han
>
> >
> > * Introduce northd_init() which initializes this data.
> > * Introduce northd_destroy() which clears this data for a new iteration.
> > * Remove 'ovn_internal_version' from the context passed to northd
> >   as it can be determined within northd using ovn_get_internal_version.
> > * Remove 'use_parallel_build' from the context as it is read from DB as
> >   suggested by Han.
> > * Refactor northd.c to use 'struct northd_data' and 'struct northd_input'
> >   where applicable.
> >
> > Signed-off-by: Mark Gray 
> > ---
> >
> > Notes:
> > v4: Add northd_input (move DB references and indexes to this struct)
> > Remove the use of client_ctx from engine_context
> >
> >  lib/inc-proc-eng.h   |   3 +
> >  northd/en-northd.c   | 106 ++-
> >  northd/inc-proc-northd.c |  42 ++-
> >  northd/inc-proc-northd.h |   6 +-
> >  northd/northd.c  | 603 +--
> >  northd/northd.h  |  75 -
> >  northd/ovn-northd.c  |  85 ++
> >  7 files changed, 568 insertions(+), 352 deletions(-)
> >
> > diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
> > index f89a40bd54ca..1823750c814c 100644
> > --- a/lib/inc-proc-eng.h
> > +++ b/lib/inc-proc-eng.h
> > @@ -72,6 +72,9 @@ struct engine_context {
> >  struct ovsdb_idl_txn *ovs_idl_txn;
> >  struct ovsdb_idl_txn *ovnsb_idl_txn;
> >  struct ovsdb_idl_txn *ovnnb_idl_txn;
> > +
> > +struct ovsdb_idl_loop *ovnsb_idl_loop;
> > +
> >  void *client_ctx;
> >  };
> >
> > diff --git a/northd/en-northd.c b/northd/en-northd.c
> > index d310fa4dd31f..36ea890535fe 100644
> > --- a/northd/en-northd.c
> > +++ b/northd/en-northd.c
> > @@ -20,26 +20,122 @@
> >
> >  #include "en-northd.h"
> >  #include "lib/inc-proc-eng.h"
> > +#include "openvswitch/list.h" /* TODO This is needed for
> ovn-parallel-hmap.h.
> > +   * lib/ovn-parallel-hmap.h should be
> updated
> > +   * to include this dependency itself */
> > +#include "lib/ovn-parallel-hmap.h"
> >  #include "northd.h"
>

Re: [ovs-dev] [PATCH ovn v4 6/6] northd: Do not calculate database sequence numbers incrementally

2021-11-08 Thread Mark Gray
On Thu, Nov 4, 2021 at 12:02 AM Han Zhou  wrote:

> On Wed, Oct 27, 2021 at 10:24 AM Mark Gray  wrote:
> >
> > In order to remove the IDL loop variable from the engine context,
> > we do not calculate the database sequence numbers incrementally.
> >
> > Signed-off-by: Mark Gray 
> > ---
> >  lib/inc-proc-eng.h   |  2 -
> >  northd/en-northd.c   |  3 +-
> >  northd/inc-proc-northd.c |  2 -
> >  northd/inc-proc-northd.h |  1 -
> >  northd/northd.c  | 84 
> >  northd/northd.h  |  3 +-
> >  northd/ovn-northd.c  | 84 ++--
> >  7 files changed, 90 insertions(+), 89 deletions(-)
> >
> > diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
> > index 1823750c814c..6f3918ae7789 100644
> > --- a/lib/inc-proc-eng.h
> > +++ b/lib/inc-proc-eng.h
> > @@ -73,8 +73,6 @@ struct engine_context {
> >  struct ovsdb_idl_txn *ovnsb_idl_txn;
> >  struct ovsdb_idl_txn *ovnnb_idl_txn;
> >
> > -struct ovsdb_idl_loop *ovnsb_idl_loop;
> > -
> >  void *client_ctx;
> >  };
> >
> > diff --git a/northd/en-northd.c b/northd/en-northd.c
> > index 36ea890535fe..295a74721678 100644
> > --- a/northd/en-northd.c
> > +++ b/northd/en-northd.c
> > @@ -119,8 +119,7 @@ void en_northd_run(struct engine_node *node, void
> *data)
> >
> >  northd_run(data,
> > eng_ctx->ovnnb_idl_txn,
> > -   eng_ctx->ovnsb_idl_txn,
> > -   eng_ctx->ovnsb_idl_loop);
> > +   eng_ctx->ovnsb_idl_txn);
> >  engine_set_node_state(node, EN_UPDATED);
> >
> >  }
> > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
> > index 56c05a0fd6f3..44b53432c071 100644
> > --- a/northd/inc-proc-northd.c
> > +++ b/northd/inc-proc-northd.c
> > @@ -248,7 +248,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> >
> >  void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
> >   struct ovsdb_idl_txn *ovnsb_txn,
> > - struct ovsdb_idl_loop *ovnsb_idl_loop,
> >   bool recompute) {
> >  engine_set_force_recompute(recompute);
> >  engine_init_run();
> > @@ -256,7 +255,6 @@ void inc_proc_northd_run(struct ovsdb_idl_txn
> *ovnnb_txn,
> >  struct engine_context eng_ctx = {
> >  .ovnnb_idl_txn = ovnnb_txn,
> >  .ovnsb_idl_txn = ovnsb_txn,
> > -.ovnsb_idl_loop = ovnsb_idl_loop,
> >  };
> >
> >  engine_set_context(_ctx);
> > diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
> > index 4aeb387b7b0f..1300253791b6 100644
> > --- a/northd/inc-proc-northd.h
> > +++ b/northd/inc-proc-northd.h
> > @@ -10,7 +10,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> >struct ovsdb_idl_loop *sb);
> >  void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
> >   struct ovsdb_idl_txn *ovnsb_txn,
> > - struct ovsdb_idl_loop *ovnsb_idl_loop,
> >   bool recompute);
> >  void inc_proc_northd_cleanup(void);
> >
> > diff --git a/northd/northd.c b/northd/northd.c
> > index 7bccd054cdb4..1e4273ec5e88 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -14502,9 +14502,7 @@ ovnnb_db_run(struct northd_data *data,
> >   struct ovsdb_idl_txn *ovnnb_txn,
> >   struct ovsdb_idl_txn *ovnsb_txn,
> >   struct ovsdb_idl_index *sbrec_chassis_by_name,
> > - struct ovsdb_idl_index *sbrec_chassis_by_hostname,
> > - struct ovsdb_idl_loop *sb_loop,
> > - int64_t loop_start_time)
> > + struct ovsdb_idl_index *sbrec_chassis_by_hostname)
> >  {
> >  if (!ovnsb_txn || !ovnnb_txn) {
> >  return;
> > @@ -14527,12 +14525,7 @@ ovnnb_db_run(struct northd_data *data,
> >  if (nb->ipsec != sb->ipsec) {
> >  sbrec_sb_global_set_ipsec(sb, nb->ipsec);
> >  }
> > -if (nb->nb_cfg != sb->nb_cfg) {
> > -sbrec_sb_global_set_nb_cfg(sb, nb->nb_cfg);
> > -nbrec_nb_global_set_nb_cfg_timestamp(nb, loop_start_time);
> > -}
> >  sbrec_sb_global_set_options(sb, >options);
> > -sb_loop->next_cfg = nb->nb_cfg;
> >
> >  const char *mac_addr_prefix = set_mac_prefix(smap_get(>options,
> >
> "mac_prefix"));
>

Re: [ovs-dev] [PATCH v2 ovn 2/3] CoPP: add self-test for bfd controller action

2021-10-29 Thread Mark Gray
On 21/10/2021 23:18, Lorenzo Bianconi wrote:
> Introduce CoPP selftest for bfd controller action
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  tests/system-ovn.at | 28 
>  1 file changed, 28 insertions(+)
> 
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index d003843c3..77c811946 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -6743,6 +6743,34 @@ OVS_WAIT_UNTIL([
>  ])
>  kill $(pidof tcpdump)
>  
> +check ovn-nbctl meter-add bfd-meter drop 1 pktps 0
> +check ovn-nbctl --wait=hv lr-copp-add R1 bfd bfd-meter
> +AT_CHECK([ovn-nbctl lr-copp-list R1 |grep bfd], [0], [dnl
> +bfd: bfd-meter
> +])
> +
> +check ovn-nbctl --bfd lr-route-add R1 240.0.0.0/8 172.16.1.50 rp-public
> +printf "%08x" $(ovn-sbctl get bfd . disc) > /tmp/disc
> +NS_EXEC([server], [tcpdump -l -n -i s1 udp port 3784 -Q in > bfd.pcap &])
> +ip netns exec server scapy -H <<-EOF
> +import binascii
> +f = open("/tmp/disc", "r")
> +# scapy does not support BFD protocol
> +# let's hardcode a BFD payload with the proper my-disc field read from the db
> +bfd = binascii.unhexlify("20600518a899e77b" + f.readline().strip() + 
> "000f424f4240")
> +p = IP(src="172.16.1.50", dst="172.16.1.1") / UDP(dport = 3784, sport = 
> 49152) / Raw(load = bfd)
> +send (p, iface='s1', loop = 0, verbose = 0, count = 100)
> +f.close()
> +EOF
> +rm /tmp/disc
> +
> +# 1pps + 1 burst size
> +OVS_WAIT_UNTIL([
> +n_tcp_rst=$(grep Final bfd.pcap | wc -l)
> +test "${n_tcp_rst}" = "2"
> +])
> +kill $(pidof tcpdump)
> +
>  kill $(pidof ovn-controller)
>  
>  as ovn-sb
> 
Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2 ovn 3/3] CoPP: add self-test for tcp-reset controller action

2021-10-29 Thread Mark Gray
On 21/10/2021 23:18, Lorenzo Bianconi wrote:
> Introduce CoPP selftest for tcp-reset controller action
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  tests/ovn-northd.at | 11 +++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 3ff0029f8..afc005156 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -3272,6 +3272,17 @@ check ovn-nbctl --wait=hv lr-copp-del r0 icmp6-error
>  AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
>  ])
>  
> +check ovn-nbctl --wait=hv lr-copp-add r0 tcp-reset meter2
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +tcp-reset: meter2
> +])
> +
> +AT_CHECK([ovn-sbctl list logical_flow | grep tcp -A 2 | grep -q meter2])
> +
> +check ovn-nbctl --wait=hv lr-copp-del r0 tcp-reset
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +])
> +
>  check ovn-nbctl --wait=hv ls-copp-del sw1 event-elb
>  AT_CHECK([ovn-nbctl ls-copp-list sw1], [0], [dnl
>  ])
> 
Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2 ovn 1/3] CoPP: add self-test for icmp{4, 6}_error controller action

2021-10-29 Thread Mark Gray
On 21/10/2021 23:18, Lorenzo Bianconi wrote:
> Introduce CoPP selftest for icmp{4,6}_error controller action
> Remove sleep in CoPP test and rely on tcpdump "-l" option.
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  tests/ovn-northd.at | 23 +++
>  tests/system-ovn.at | 43 ---
>  2 files changed, 51 insertions(+), 15 deletions(-)
> 
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 544820764..3ff0029f8 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -3249,6 +3249,29 @@ AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
>  
>  AT_CHECK([ovn-sbctl list logical_flow | grep arp -A 2 | grep -q meter1],[1])
>  
> +check ovn-nbctl --wait=hv meter-add meter2 drop 400 pktps 10
> +check ovn-nbctl --wait=hv lr-copp-add r0 icmp4-error meter2
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +icmp4-error: meter2
> +])
> +
> +AT_CHECK([ovn-sbctl list logical_flow | grep icmp4 -A 2 | grep -q meter2])
> +
> +check ovn-nbctl --wait=hv lr-copp-del r0 icmp4-error
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +])
> +
> +check ovn-nbctl --wait=hv lr-copp-add r0 icmp6-error meter2
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +icmp6-error: meter2
> +])
> +
> +AT_CHECK([ovn-sbctl list logical_flow | grep icmp6 -A 2 | grep -q meter2])
> +
> +check ovn-nbctl --wait=hv lr-copp-del r0 icmp6-error
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +])
> +
>  check ovn-nbctl --wait=hv ls-copp-del sw1 event-elb
>  AT_CHECK([ovn-nbctl ls-copp-list sw1], [0], [dnl
>  ])
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 345384223..d003843c3 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -6669,7 +6669,7 @@ check ovn-nbctl lsp-add public public1 \
>  -- lsp-set-type public1 localnet \
>  -- lsp-set-options public1 network_name=phynet
>  
> -NS_EXEC([sw01], [tcpdump -n -i sw01 icmp -Q in > reject.pcap &])
> +NS_EXEC([sw01], [tcpdump -l -n -i sw01 icmp -Q in > reject.pcap &])
>  check ovn-nbctl meter-add acl-meter drop 1 pktps 0
>  check ovn-nbctl --wait=hv ls-copp-add sw0 reject acl-meter
>  check ovn-nbctl acl-add sw0 from-lport 1002 'inport == "sw01" && ip && udp' 
> reject
> @@ -6679,37 +6679,33 @@ reject: acl-meter
>  ])
>  
>  ip netns exec sw01 scapy -H <<-EOF
> -p = IP(src="192.168.1.2", dst="192.168.1.1")/ UDP(dport = 12345) / 
> Raw(b"X"*64)
> +p = IP(src="192.168.1.2", dst="192.168.1.1") / UDP(dport = 12345) / 
> Raw(b"X"*64)
>  send (p, iface='sw01', loop = 0, verbose = 0, count = 20)
>  EOF
>  
> -sleep 2
> -kill $(pidof tcpdump)
> -
>  # 1pps + 1 burst size
>  OVS_WAIT_UNTIL([
>  n_reject=$(grep unreachable reject.pcap | wc -l)
>  test "${n_reject}" = "2"
>  ])
> +kill $(pidof tcpdump)
>  
>  rm -f reject.pcap
> -NS_EXEC([sw01], [tcpdump -n -i sw01 icmp -Q in > reject.pcap &])
> +NS_EXEC([sw01], [tcpdump -l -n -i sw01 icmp -Q in > reject.pcap &])
>  check ovn-nbctl --wait=hv ls-copp-del sw0 reject
>  
>  ip netns exec sw01 scapy -H <<-EOF
> -p = IP(src="192.168.1.2", dst="192.168.1.1")/ UDP(dport = 12345) / 
> Raw(b"X"*64)
> +p = IP(src="192.168.1.2", dst="192.168.1.1") / UDP(dport = 12345) / 
> Raw(b"X"*64)
>  send (p, iface='sw01', loop = 0, verbose = 0, count = 20)
>  EOF
>  
> -sleep 2
> -kill $(pidof tcpdump)
> -
>  OVS_WAIT_UNTIL([
>  n_reject=$(grep unreachable reject.pcap | wc -l)
>  test "${n_reject}" = "20"
>  ])
> +kill $(pidof tcpdump)
>  
> -NS_EXEC([server], [tcpdump -n -i s1 arp[[24:4]]=0xac100164 > arp.pcap &])
> +NS_EXEC([server], [tcpdump -l -n -i s1 arp[[24:4]]=0xac100164 > arp.pcap &])
>  check ovn-nbctl meter-add arp-meter drop 1 pktps 0
>  check ovn-nbctl --wait=hv lr-copp-add R1 arp-resolve arp-meter
>  AT_CHECK([ovn-nbctl lr-copp-list R1], [0], [dnl
> @@ -6717,18 +6713,35 @@ arp-resolve: arp-meter
>  ])
>  
>  ip netns exec sw01 scapy -H <<-EOF
> -p = IP(src="192.168.1.2", dst="172.16.1.100")/ TCP(dport = 80, flags="S") / 
> Raw(b"X"*64)
> +p = IP(src="192.168.1.2", dst="172.16.1.100") / TCP(dport = 80, flags="S") / 
> Raw(b"X"*64)
>  send (p, iface='sw01', loop = 0, verbose = 0, count = 100)
>  EOF
>  
> -sleep 2
> -kill $(pidof tcpdump)
> -
>  # 1pps + 1 burst size
>  OVS_WAIT_UNTIL([
>  n_arp=$(grep ARP arp.pcap | wc -l)
>  test "${n_arp}" = "2"
>  ])
> +kill $(pidof tcpdump)
> +
> +check ovn-nbctl meter-add icmp-meter drop 1 pktps 0
> +check ovn-nbctl --wait=hv lr-copp-add R1 icmp4-error icmp-meter
> +AT_CHECK([ovn-nbctl lr-copp-list R1 |grep icmp4-error], [0], [dnl
> +icmp4-error: icmp-meter
> +])
> +
> +NS_EXEC([sw01], [tcpdump -l -n -i sw01 icmp > icmp.pcap &])
> +ip netns exec sw01 scapy -H <<-EOF
> +p = IP(src="192.168.1.2", dst="172.16.1.100", ttl=1) / TCP(dport = 8080, 
> flags="S") / Raw(b"X"*64)
> +send (p, iface='sw01', loop = 0, verbose = 0, count = 100)
> +EOF
> +
> +# 1pps + 1 burst size
> +OVS_WAIT_UNTIL([
> +n_icmp=$(grep ICMP icmp.pcap | wc -l)
> +test "${n_icmp}" = "2"
> +])
> +kill $(pidof 

Re: [ovs-dev] [PATCH ovn v4 4/6] northd: Introduce struct northd_data

2021-10-27 Thread Mark Gray
On 27/10/2021 18:53, 0-day Robot wrote:
> Bleep bloop.  Greetings Mark Gray, I am a robot and I have tried out your 
> patch.
> Thanks for your contribution.
> 
> I encountered some error that I wasn't expecting.  See the details below.
> 
> 
> checkpatch:
> WARNING: Comment with 'xxx' marker
> #1478 FILE: northd/northd.c:14488:
> /* XXX Having to explicitly clean up macam here

This 'XXX' did not originate in this patch but was triggered by moving
it to a different location.

> 
> Lines checked: 2148, Warnings: 1, Errors: 0
> 
> 
> Please check this out.  If you feel there has been an error, please email 
> acon...@redhat.com
> 
> Thanks,
> 0-day Robot
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v3 2/7] northd: Introduce incremental processing for northd

2021-10-27 Thread Mark Gray
On 27/10/2021 07:00, Han Zhou wrote:
> I would suggest using a separate structure, such as "northd_input" (or a
> better name) to include the index and tables. The data of en_northd should
> only contain the data generated by the engine node (i.e. output data).
> 
> Thanks,
> Han

Thanks for all your suggestions. I took the onboard. New series at:
https://patchwork.ozlabs.org/project/ovn/list/?series=269213

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v4 6/6] northd: Do not calculate database sequence numbers incrementally

2021-10-27 Thread Mark Gray
In order to remove the IDL loop variable from the engine context,
we do not calculate the database sequence numbers incrementally.

Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  2 -
 northd/en-northd.c   |  3 +-
 northd/inc-proc-northd.c |  2 -
 northd/inc-proc-northd.h |  1 -
 northd/northd.c  | 84 
 northd/northd.h  |  3 +-
 northd/ovn-northd.c  | 84 ++--
 7 files changed, 90 insertions(+), 89 deletions(-)

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 1823750c814c..6f3918ae7789 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -73,8 +73,6 @@ struct engine_context {
 struct ovsdb_idl_txn *ovnsb_idl_txn;
 struct ovsdb_idl_txn *ovnnb_idl_txn;
 
-struct ovsdb_idl_loop *ovnsb_idl_loop;
-
 void *client_ctx;
 };
 
diff --git a/northd/en-northd.c b/northd/en-northd.c
index 36ea890535fe..295a74721678 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -119,8 +119,7 @@ void en_northd_run(struct engine_node *node, void *data)
 
 northd_run(data,
eng_ctx->ovnnb_idl_txn,
-   eng_ctx->ovnsb_idl_txn,
-   eng_ctx->ovnsb_idl_loop);
+   eng_ctx->ovnsb_idl_txn);
 engine_set_node_state(node, EN_UPDATED);
 
 }
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 56c05a0fd6f3..44b53432c071 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -248,7 +248,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
- struct ovsdb_idl_loop *ovnsb_idl_loop,
  bool recompute) {
 engine_set_force_recompute(recompute);
 engine_init_run();
@@ -256,7 +255,6 @@ void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
 struct engine_context eng_ctx = {
 .ovnnb_idl_txn = ovnnb_txn,
 .ovnsb_idl_txn = ovnsb_txn,
-.ovnsb_idl_loop = ovnsb_idl_loop,
 };
 
 engine_set_context(_ctx);
diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
index 4aeb387b7b0f..1300253791b6 100644
--- a/northd/inc-proc-northd.h
+++ b/northd/inc-proc-northd.h
@@ -10,7 +10,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb);
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
- struct ovsdb_idl_loop *ovnsb_idl_loop,
  bool recompute);
 void inc_proc_northd_cleanup(void);
 
diff --git a/northd/northd.c b/northd/northd.c
index 7bccd054cdb4..1e4273ec5e88 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -14502,9 +14502,7 @@ ovnnb_db_run(struct northd_data *data,
  struct ovsdb_idl_txn *ovnnb_txn,
  struct ovsdb_idl_txn *ovnsb_txn,
  struct ovsdb_idl_index *sbrec_chassis_by_name,
- struct ovsdb_idl_index *sbrec_chassis_by_hostname,
- struct ovsdb_idl_loop *sb_loop,
- int64_t loop_start_time)
+ struct ovsdb_idl_index *sbrec_chassis_by_hostname)
 {
 if (!ovnsb_txn || !ovnnb_txn) {
 return;
@@ -14527,12 +14525,7 @@ ovnnb_db_run(struct northd_data *data,
 if (nb->ipsec != sb->ipsec) {
 sbrec_sb_global_set_ipsec(sb, nb->ipsec);
 }
-if (nb->nb_cfg != sb->nb_cfg) {
-sbrec_sb_global_set_nb_cfg(sb, nb->nb_cfg);
-nbrec_nb_global_set_nb_cfg_timestamp(nb, loop_start_time);
-}
 sbrec_sb_global_set_options(sb, >options);
-sb_loop->next_cfg = nb->nb_cfg;
 
 const char *mac_addr_prefix = set_mac_prefix(smap_get(>options,
   "mac_prefix"));
@@ -14834,68 +14827,12 @@ handle_port_binding_changes(struct northd_data *data,
 }
 }
 
-/* Updates the sb_cfg and hv_cfg columns in the northbound NB_Global table. */
-static void
-update_northbound_cfg(struct northd_data *data,
-  struct ovsdb_idl_loop *sb_loop,
-  int64_t loop_start_time)
-{
-/* Update northbound sb_cfg if appropriate. */
-const struct nbrec_nb_global *nbg = nbrec_nb_global_table_first(
-   data->input.nbrec_nb_global_table);
-int64_t sb_cfg = sb_loop->cur_cfg;
-if (nbg && sb_cfg && nbg->sb_cfg != sb_cfg) {
-nbrec_nb_global_set_sb_cfg(nbg, sb_cfg);
-nbrec_nb_global_set_sb_cfg_timestamp(nbg, loop_start_time);
-}
-
-/* Update northbound hv_cfg if appropriate. */
-if (nbg) {
-/* Find minimum nb_cfg among all chassis. */
-const struct sbrec_chassis_private *chassis_priv;
-int64_t hv_cfg = nbg->nb_cfg;
-int64_t hv_cfg_ts = 0;
-SBREC_CHASSIS

[ovs-dev] [PATCH ovn v4 4/6] northd: Introduce struct northd_data

2021-10-27 Thread Mark Gray
'struct northd_data' is used to hold the global state data for the
incremental processing node 'en_northd'. This structure will also hold
'struct northd_input' which will hold references to output data from
its input nodes. In particular, this will hold references to database tables
and indexes. In order to achieve this, we refactor in the following way:

* Introduce northd_init() which initializes this data.
* Introduce northd_destroy() which clears this data for a new iteration.
* Remove 'ovn_internal_version' from the context passed to northd
  as it can be determined within northd using ovn_get_internal_version.
* Remove 'use_parallel_build' from the context as it is read from DB as
  suggested by Han.
* Refactor northd.c to use 'struct northd_data' and 'struct northd_input'
  where applicable.

Signed-off-by: Mark Gray 
---

Notes:
v4: Add northd_input (move DB references and indexes to this struct)
Remove the use of client_ctx from engine_context

 lib/inc-proc-eng.h   |   3 +
 northd/en-northd.c   | 106 ++-
 northd/inc-proc-northd.c |  42 ++-
 northd/inc-proc-northd.h |   6 +-
 northd/northd.c  | 603 +--
 northd/northd.h  |  75 -
 northd/ovn-northd.c  |  85 ++
 7 files changed, 568 insertions(+), 352 deletions(-)

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index f89a40bd54ca..1823750c814c 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -72,6 +72,9 @@ struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
 struct ovsdb_idl_txn *ovnnb_idl_txn;
+
+struct ovsdb_idl_loop *ovnsb_idl_loop;
+
 void *client_ctx;
 };
 
diff --git a/northd/en-northd.c b/northd/en-northd.c
index d310fa4dd31f..36ea890535fe 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -20,26 +20,122 @@
 
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
+#include "openvswitch/list.h" /* TODO This is needed for ovn-parallel-hmap.h.
+   * lib/ovn-parallel-hmap.h should be updated
+   * to include this dependency itself */
+#include "lib/ovn-parallel-hmap.h"
 #include "northd.h"
+#include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
 
-void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+void en_northd_run(struct engine_node *node, void *data)
 {
 const struct engine_context *eng_ctx = engine_get_context();
-struct northd_context *ctx = eng_ctx->client_ctx;
-ovn_db_run(ctx);
 
+northd_destroy(data);
+northd_init(data);
+
+struct northd_data *northd_data = data;
+northd_data->input.sbrec_chassis_by_name =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_chassis", node),
+"sbrec_chassis_by_name");
+northd_data->input.sbrec_chassis_by_hostname =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_chassis", node),
+"sbrec_chassis_by_hostname");
+northd_data->input.sbrec_ha_chassis_grp_by_name =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_ha_chassis_group", node),
+"sbrec_ha_chassis_grp_by_name");
+northd_data->input.sbrec_mcast_group_by_name_dp =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_multicast_group", node),
+"sbrec_mcast_group_by_name");
+northd_data->input.sbrec_ip_mcast_by_dp =
+engine_ovsdb_node_get_index(
+engine_get_input("SB_ip_multicast", node),
+"sbrec_ip_mcast_by_dp");
+
+northd_data->input.nbrec_nb_global_table =
+EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
+northd_data->input.nbrec_logical_switch =
+EN_OVSDB_GET(engine_get_input("NB_logical_switch", node));
+northd_data->input.nbrec_logical_router =
+EN_OVSDB_GET(engine_get_input("NB_logical_router", node));
+northd_data->input.nbrec_load_balancer_table =
+EN_OVSDB_GET(engine_get_input("NB_load_balancer", node));
+northd_data->input.nbrec_port_group_table =
+EN_OVSDB_GET(engine_get_input("NB_port_group", node));
+northd_data->input.nbrec_bfd_table =
+EN_OVSDB_GET(engine_get_input("NB_bfd", node));
+northd_data->input.nbrec_address_set_table =
+EN_OVSDB_GET(engine_get_input("NB_address_set", node));
+northd_data->input.nbrec_meter_table =
+EN_OVSDB_GET(engine_get_input("NB_meter", node));
+northd_data->input.nbrec_acl_table =
+EN_OVSDB_GET(engine_get_input("NB_acl", node));
+
+northd_data->input.sbrec_sb_global_table =
+EN_O

[ovs-dev] [PATCH ovn v4 2/6] northd: Introduce incremental processing for northd

2021-10-27 Thread Mark Gray
Initial implementation adds a single node (northd). This single
node executes the northd processing pipeline but does not do so
incrementally.

In order to develop incremental processing for northd, the code
will be organised with a .c/.h file for each I-P node following
the naming convention en-.c/.h. These files will
contain definition of the node data, the main node processing
functions and change handlers (if any). The purpose of these nodes
will be coordination of the nodes work and implemention of the
relevant interfaces to plug into the I-P framework. The actual
work that will be executed by the node will be organised into
a companion file or files. Ideally this file will follow the
naming convention of the node: e.g. en-.c is
associated with .c.

Initial node topology sees the northd node dependent on all DB
nodes. This will evolve over time.

Co-authored-by: Numan Siddique 
Signed-off-by: Numan Siddique 
Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  16 +++
 northd/automake.mk   |   4 +
 northd/en-northd.c   |  45 +++
 northd/en-northd.h   |  17 +++
 northd/inc-proc-northd.c | 254 +++
 northd/inc-proc-northd.h |  15 +++
 northd/northd.c  |  16 ++-
 northd/northd.h  |  11 +-
 northd/ovn-northd.c  | 211 
 9 files changed, 498 insertions(+), 91 deletions(-)
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 36495fdf8a94..f89a40bd54ca 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -63,15 +63,22 @@
 #define ENGINE_MAX_INPUT 256
 #define ENGINE_MAX_OVSDB_INDEX 256
 
+#include 
+#include 
+
+#include "compiler.h"
+
 struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
+struct ovsdb_idl_txn *ovnnb_idl_txn;
 void *client_ctx;
 };
 
 /* Arguments to be passed to the engine at engine_init(). */
 struct engine_arg {
 struct ovsdb_idl *sb_idl;
+struct ovsdb_idl *nb_idl;
 struct ovsdb_idl *ovs_idl;
 };
 
@@ -344,6 +351,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_FUNC_SB(TBL_NAME) \
 ENGINE_FUNC_OVSDB(sb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN NB DB */
+#define ENGINE_FUNC_NB(TBL_NAME) \
+ENGINE_FUNC_OVSDB(nb, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -357,6 +369,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
 ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
 
+/* Macro to define an engine node which represents a table of OVN NB DB */
+#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
+ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
diff --git a/northd/automake.mk b/northd/automake.mk
index 35ad8c09d9ba..f0c1fb11c83a 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
northd/northd.c \
northd/northd.h \
northd/ovn-northd.c \
+   northd/en-northd.c \
+   northd/en-northd.h \
+   northd/inc-proc-northd.c \
+   northd/inc-proc-northd.h \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/en-northd.c b/northd/en-northd.c
new file mode 100644
index ..d310fa4dd31f
--- /dev/null
+++ b/northd/en-northd.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-northd.h"
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_northd);
+
+void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_context *ctx = eng_ctx->client_ctx;
+ovn_db_run(ctx);
+
+engine_set_node_state(node, EN_UPDATED);

[ovs-dev] [PATCH ovn v4 3/6] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-10-27 Thread Mark Gray
destroy_nat_entries() iterates over nat_entries using 'n_nat'
as the number of NAT entries from the NB database. This behaviour can be
incorrect as it assumes that there are 'n_nat' 'nat_entries'. 'struct
ovn_datapath' should maintain a count of 'nat_entries' in 'struct
ovn_datapath' rather than read the value from NBDB IDL to properly
account for the number of 'nat_entries'.

This issue becomes apparent when using destroy_nat_entries()
as part of an incremental processing loop:

Consider an example in which we have completed iteration x, and
started iteration x+1. If we add a NAT entry to NBDB between iteration x
and iteration x+1, od->nbr->n_nat will contain the updated value of
n_nat as the northbound record will have been updated. However, if
we do not (re)initialize the nat entries in od, od->n_nat_entries
could be equal to the previous value. This can cause destroy_nat_entries()
to loop over the wrong number of 'nat_entries' causing unexpected
behaviour.

Acked-by: Han Zhou 
Signed-off-by: Mark Gray 
---

Notes:
v4: Added Han's Ack
Fixed typo in comment

 northd/northd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/northd/northd.c b/northd/northd.c
index 440838435940..455b9b0e867a 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -603,6 +603,8 @@ struct ovn_datapath {
 
 /* NAT entries configured on the router. */
 struct ovn_nat *nat_entries;
+size_t n_nat_entries;
+
 bool has_distributed_nat;
 
 /* Set of nat external ips on the router. */
@@ -787,6 +789,7 @@ init_nat_entries(struct ovn_datapath *od)
 od->has_distributed_nat = true;
 }
 }
+od->n_nat_entries = od->nbr->n_nat;
 }
 
 static void
@@ -800,7 +803,7 @@ destroy_nat_entries(struct ovn_datapath *od)
 destroy_lport_addresses(>dnat_force_snat_addrs);
 destroy_lport_addresses(>lb_force_snat_addrs);
 
-for (size_t i = 0; i < od->nbr->n_nat; i++) {
+for (size_t i = 0; i < od->n_nat_entries; i++) {
 destroy_lport_addresses(>nat_entries[i].ext_addrs);
 }
 }
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v4 1/6] inc-proc-eng: Allow definition of engine_node with global scope

2021-10-27 Thread Mark Gray
Refactor ENGINE_NODE() macro to not assign function pointers. This
allows ENGINE_NODE() to be used outside functions, creating an
engine_node with global scope (but can be statically defined within a file).
This allows more flexibility in how the I-P engine can be used.
Although this is not explicitly required for I-P it does allow for a cleaner
code base as the node definitions can be kept together outside any functions.

Additional function pointers (e.g. is_valid(), clear_tracked_data()),
may be assigned later, if required.

Acked-by: Han Zhou 
Signed-off-by: Mark Gray 
---

Notes:
v4: Update based on Han's comments
Fixed typos in comment

 controller/ovn-controller.c |  2 +-
 lib/inc-proc-eng.h  | 13 +
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 92ba50d6532c..4d99da03a275 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -3196,7 +3196,7 @@ main(int argc, char *argv[])
 stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
 
 /* Define inc-proc-engine nodes. */
-ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones");
+ENGINE_NODE_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones, "ct_zones");
 ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
 ENGINE_NODE(non_vif_data, "non_vif_data");
 ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 859b30a71c86..36495fdf8a94 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -295,19 +295,16 @@ void engine_ovsdb_node_add_index(struct engine_node *, 
const char *name,
 .init = en_##NAME##_init, \
 .run = en_##NAME##_run, \
 .cleanup = en_##NAME##_cleanup, \
-.is_valid = en_##NAME##_is_valid, \
+.is_valid = NULL, \
 .clear_tracked_data = NULL, \
 };
 
-#define ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
-ENGINE_NODE_DEF(NAME, NAME_STR)
-
-#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
-ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
-en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data;
+#define ENGINE_NODE_WITH_CLEAR_TRACK_DATA_IS_VALID(NAME, NAME_STR) \
+ENGINE_NODE(NAME, NAME_STR) \
+en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data; \
+en_##NAME.is_valid = en_##NAME##_is_valid;
 
 #define ENGINE_NODE(NAME, NAME_STR) \
-static bool (*en_##NAME##_is_valid)(struct engine_node *node) = NULL; \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
 #define ENGINE_NODE_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v4 0/6] northd: Introduce incremental processing framework

2021-10-27 Thread Mark Gray
Add the 'inc-proc-eng' framework to northd. This does *not*
add any incremental processing at this stage but provides the
framework to do so. Even in this base configuration, we see an
advantage as northd no longer processes the databases if it has
been woken only to handle, for example, a unixctl command. This
can be seen below

$ ovn-appctl -t ovn-northd stopwatch/reset
$ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show >/dev/null; done
$ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Statistics for 'ovnnb_db_run'
  Total samples: 0
  Maximum: 0 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 0.00 msec
  Long term average: 0.00 msec

Hopefully this starting point will allow others to discuss or contribute
changes to incrementally process some aspects of northd. We an also
decide if it is worth progressing with this in general.

Thanks,

v2: Rebase
v3: Fix compile error in 2/7 picked up by 0-day robot
v4: Rework based on Han's comments and rebase

Mark Gray (6):
  inc-proc-eng: Allow definition of engine_node with global scope
  northd: Introduce incremental processing for northd
  northd: Add n_nat_entries field to 'struct ovn_datapath'
  northd: Introduce struct northd_data
  northd: Add lflow node
  northd: Do not calculate database sequence numbers incrementally

 controller/ovn-controller.c |   2 +-
 lib/inc-proc-eng.h  |  30 +-
 northd/automake.mk  |   6 +
 northd/en-lflow.c   |  53 +++
 northd/en-lflow.h   |  16 +
 northd/en-northd.c  | 140 
 northd/en-northd.h  |  17 +
 northd/inc-proc-northd.c| 287 +++
 northd/inc-proc-northd.h|  16 +
 northd/northd.c | 671 ++--
 northd/northd.h |  77 -
 northd/ovn-northd.c | 357 ---
 12 files changed, 1181 insertions(+), 491 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

-- 
2.27.0


___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v3 4/7] northd: Rename struct northd_context

2021-10-26 Thread Mark Gray
On 25/10/2021 01:30, Han Zhou wrote:
> On Mon, Oct 18, 2021 at 5:14 AM Mark Gray  wrote:
>>
>> In order to prepare for a subsequent commit, rename
>> 'struct northd_context' to 'struct northd_idl_context'. In
>> subsequent commits, 'struct northd_idl_context' will then be
>> used, only, to hold the IDL context required by northd.
> 
> This patch itself looks good, but regarding this commit message I think the
> struct shouldn't even be necessary. nb_idl_txn and sb_idl_txn are both
> available in the I-P engine context, and as mentioned in my comment for
> patch 2, the other fields shouldn't exist in the context that can be
> accessed by all engine nodes.
> 

Ok

> Thanks,
> Han
> 
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  northd/en-northd.c   |  2 +-
>>  northd/inc-proc-northd.c |  2 +-
>>  northd/inc-proc-northd.h |  2 +-
>>  northd/northd.c  | 89 
>>  northd/northd.h  |  4 +-
>>  northd/ovn-northd.c  | 10 ++---
>>  6 files changed, 55 insertions(+), 54 deletions(-)
>>
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> index d310fa4dd31f..8dec51535af0 100644
>> --- a/northd/en-northd.c
>> +++ b/northd/en-northd.c
>> @@ -28,7 +28,7 @@ VLOG_DEFINE_THIS_MODULE(en_northd);
>>  void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
>>  {
>>  const struct engine_context *eng_ctx = engine_get_context();
>> -struct northd_context *ctx = eng_ctx->client_ctx;
>> +struct northd_idl_context *ctx = eng_ctx->client_ctx;
>>  ovn_db_run(ctx);
>>
>>  engine_set_node_state(node, EN_UPDATED);
>> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
>> index 85baeb07d3d9..572b8de6536a 100644
>> --- a/northd/inc-proc-northd.c
>> +++ b/northd/inc-proc-northd.c
>> @@ -213,7 +213,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>  engine_init(_northd, _arg);
>>  }
>>
>> -void inc_proc_northd_run(struct northd_context *ctx,
>> +void inc_proc_northd_run(struct northd_idl_context *ctx,
>>   bool recompute) {
>>  engine_set_force_recompute(recompute);
>>  engine_init_run();
>> diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
>> index 09cb8f3b3a80..6ee056dc14f5 100644
>> --- a/northd/inc-proc-northd.h
>> +++ b/northd/inc-proc-northd.h
>> @@ -8,7 +8,7 @@
>>
>>  void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>struct ovsdb_idl_loop *sb);
>> -void inc_proc_northd_run(struct northd_context *ctx,
>> +void inc_proc_northd_run(struct northd_idl_context *ctx,
>>   bool recompute);
>>  void inc_proc_northd_cleanup(void);
>>
>> diff --git a/northd/northd.c b/northd/northd.c
>> index 9e84ee6310a9..d61368c1e406 100644
>> --- a/northd/northd.c
>> +++ b/northd/northd.c
>> @@ -1256,7 +1256,7 @@ ovn_datapath_update_external_ids(struct
> ovn_datapath *od)
>>  }
>>
>>  static void
>> -join_datapaths(struct northd_context *ctx, struct hmap *datapaths,
>> +join_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
>> struct ovs_list *sb_only, struct ovs_list *nb_only,
>> struct ovs_list *both, struct ovs_list *lr_list)
>>  {
>> @@ -1367,7 +1367,7 @@ is_vxlan_mode(struct ovsdb_idl *ovnsb_idl)
>>  }
>>
>>  static uint32_t
>> -get_ovn_max_dp_key_local(struct northd_context *ctx)
>> +get_ovn_max_dp_key_local(struct northd_idl_context *ctx)
>>  {
>>  if (is_vxlan_mode(ctx->ovnsb_idl)) {
>>  /* OVN_MAX_DP_GLOBAL_NUM doesn't apply for vxlan mode. */
>> @@ -1377,7 +1377,7 @@ get_ovn_max_dp_key_local(struct northd_context *ctx)
>>  }
>>
>>  static void
>> -ovn_datapath_allocate_key(struct northd_context *ctx,
>> +ovn_datapath_allocate_key(struct northd_idl_context *ctx,
>>struct hmap *datapaths, struct hmap *dp_tnlids,
>>struct ovn_datapath *od, uint32_t *hint)
>>  {
>> @@ -1397,7 +1397,7 @@ ovn_datapath_allocate_key(struct northd_context
> *ctx,
>>  }
>>
>>  static void
>> -ovn_datapath_assign_requested_tnl_id(struct northd_context *ctx,
>> +ovn_datapath_assign_requested_tnl_id(struct northd_idl_context *ctx,
>>   struct hmap *dp_tnlids,
>>   struct ovn_datapath *od)
>>  {
>> @@ -1431,7 +1431,7 @@ ovn_datapath_assign_requested_

Re: [ovs-dev] [PATCH ovn v3 5/7] northd: Introduce struct northd_data

2021-10-26 Thread Mark Gray
On 25/10/2021 04:21, Han Zhou wrote:
> On Mon, Oct 18, 2021 at 5:14 AM Mark Gray  wrote:
>>
>> 'struct northd_data' is used to hold the output data from the
>> incremental processing node 'en_northd'. This will be used, in
>> a later commit, as the input data to 'en_lflow'. In order to achieve
>> this, we refactor in the following way:
>>
>> * Introduce northd_init() which initializes this data.
>> * Introduce northd_destroy() which clears this data for a new iteration.
>> * Introduce northd_indices_create() which does a one-time creation of
>>   indices for number of tables needed by northd.
>> * Remove 'ovn_internal_version' from the context passed to northd
>>   as it can be determined within northd using ovn_get_internal_version.
>> * Remove 'use_parallel_build' from the context passed to northd
>>   as it can be determined within northd using can_parallelize_hashes().
>> * Refactor northd.c to use 'struct northd_data' where applicable.
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  northd/en-northd.c  |  28 -
>>  northd/en-northd.h  |   4 +
>>  northd/northd.c | 278 
>>  northd/northd.h |  28 -
>>  northd/ovn-northd.c |  28 +
>>  5 files changed, 204 insertions(+), 162 deletions(-)
>>
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> index 8dec51535af0..1b206521e152 100644
>> --- a/northd/en-northd.c
>> +++ b/northd/en-northd.c
>> @@ -20,26 +20,46 @@
>>
>>  #include "en-northd.h"
>>  #include "lib/inc-proc-eng.h"
>> +#include "openvswitch/list.h" /* TODO This is needed for
> ovn-parallel-hmap.h.
>> +   * lib/ovn-parallel-hmap.h should be
> updated
>> +   * to include this dependency itself */
>> +#include "lib/ovn-parallel-hmap.h"
>>  #include "northd.h"
>> +#include "lib/util.h"
>>  #include "openvswitch/vlog.h"
>>
>>  VLOG_DEFINE_THIS_MODULE(en_northd);
>>
>> -void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
>> +void en_northd_run(struct engine_node *node, void *data)
>>  {
>>  const struct engine_context *eng_ctx = engine_get_context();
>>  struct northd_idl_context *ctx = eng_ctx->client_ctx;
>> -ovn_db_run(ctx);
>> +struct northd_data *northd_data = ((struct ed_type_northd
> *)data)->data;
>>
>> +northd_destroy(northd_data);
>> +northd_init(northd_data);
>> +
>> +northd_run(ctx, northd_data);
>>  engine_set_node_state(node, EN_UPDATED);
>>
>>  }
>>  void *en_northd_init(struct engine_node *node OVS_UNUSED,
>> - struct engine_arg *arg OVS_UNUSED)
>> + struct engine_arg *arg)
>>  {
>> -return NULL;
>> +struct ed_type_northd *data = xmalloc(sizeof *data);
>> +data->data = xmalloc(sizeof *data->data);
>> +
>> +data->data->use_parallel_build = can_parallelize_hashes(false);
>> +northd_indices_create(data->data, arg->sb_idl);
> 
> As mentioned in my comment in patch 2, the OVSDB indices should belong to
> the data of the corresponding OVSDB table, because 1) it is more natural,
> 2) different engine nodes can share the same input and so same OVSDB index.
> engine_ovsdb_node_add_index() can be used to add an index for an OVSDB
> table.

Yeah, I just discovered that the I-P framework allows for this model.

> 
>> +northd_init(data->data);
>> +
>> +return data;
>>  }
>>
>>  void en_northd_cleanup(void *data OVS_UNUSED)
>>  {
>> +struct northd_data *northd_data = ((struct ed_type_northd
> *)data)->data;
>> +
>> +northd_destroy(northd_data);
>> +free(northd_data);
>>  }
>> diff --git a/northd/en-northd.h b/northd/en-northd.h
>> index 0e7f76245e69..da386298d821 100644
>> --- a/northd/en-northd.h
>> +++ b/northd/en-northd.h
>> @@ -9,6 +9,10 @@
>>
>>  #include "lib/inc-proc-eng.h"
>>
>> +struct ed_type_northd {
>> +struct northd_data *data;
>> +};
> 
> northd_data is for the engine node en-northd only, so why not define it
> directly in the struct ed_type_northd? It seems unnecessary to have another
> struct that just adds one more layer when accessing the fields.
> (besides, with the current nested structure, the outer one is not freed in
> the en_northd_cleanup())

Makes sense.

> 
>> +
>>  void en_northd_run(struct engine_node *node OVS_UNU

Re: [ovs-dev] [PATCH ovn v3 2/7] northd: Introduce incremental processing for northd

2021-10-26 Thread Mark Gray
On 21/10/2021 07:30, Han Zhou wrote:
> On Mon, Oct 18, 2021 at 5:14 AM Mark Gray  wrote:
>>
>> Initial implementation adds a single node (northd). This single
>> node executes the northd processing pipeline but does not do so
>> incrementally.
>>
>> In order to develop incremental processing for northd, the code
>> will be organised with a .c/.h file for each I-P node following
>> the naming convention en-.c/.h. These files will
>> contain definition of the node data, the main node processing
>> functions and change handlers (if any). The purpose of these nodes
>> will be coordination of the nodes work and implemention of the
>> relevant interfaces to plugin to the I-P framework. The actual
>> work that will be executed by the node will be organised into
>> a companion file or files. Ideally this file will follow the
>> naming convention of the node: e.g. en-.c is
>> associated with .c.
>>
>> Initial node topology sees the northd node dependent on all DB
>> nodes. This will evolve over time.
>>
>> Co-authored-by: Numan Siddique 
>> Signed-off-by: Numan Siddique 
>> Signed-off-by: Mark Gray 
>> ---
>>  lib/inc-proc-eng.h   |  16 +++
>>  northd/automake.mk   |   4 +
>>  northd/en-northd.c   |  45 +++
>>  northd/en-northd.h   |  17 +++
>>  northd/inc-proc-northd.c | 254 +++
>>  northd/inc-proc-northd.h |  15 +++
>>  northd/northd.c  |  12 +-
>>  northd/northd.h  |   9 +-
>>  northd/ovn-northd.c  | 201 ---
>>  9 files changed, 490 insertions(+), 83 deletions(-)
>>  create mode 100644 northd/en-northd.c
>>  create mode 100644 northd/en-northd.h
>>  create mode 100644 northd/inc-proc-northd.c
>>  create mode 100644 northd/inc-proc-northd.h
>>
>> diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
>> index 1ccae559dff6..a3f5a7e64287 100644
>> --- a/lib/inc-proc-eng.h
>> +++ b/lib/inc-proc-eng.h
>> @@ -63,15 +63,22 @@
>>  #define ENGINE_MAX_INPUT 256
>>  #define ENGINE_MAX_OVSDB_INDEX 256
>>
>> +#include 
>> +#include 
>> +
>> +#include "compiler.h"
>> +
>>  struct engine_context {
>>  struct ovsdb_idl_txn *ovs_idl_txn;
>>  struct ovsdb_idl_txn *ovnsb_idl_txn;
>> +struct ovsdb_idl_txn *ovnnb_idl_txn;
> 
> It would be better to add comments to clarify for the fields used by only
> one component but not the other.
> 
>>  void *client_ctx;
>>  };
>>
>>  /* Arguments to be passed to the engine at engine_init(). */
>>  struct engine_arg {
>>  struct ovsdb_idl *sb_idl;
>> +struct ovsdb_idl *nb_idl;
>>  struct ovsdb_idl *ovs_idl;
>>  };
>>
>> @@ -347,6 +354,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void
> *data OVS_UNUSED) \
>>  #define ENGINE_FUNC_SB(TBL_NAME) \
>>  ENGINE_FUNC_OVSDB(sb, TBL_NAME)
>>
>> +/* Macro to define member functions of an engine node which represents
>> + * a table of OVN NB DB */
>> +#define ENGINE_FUNC_NB(TBL_NAME) \
>> +ENGINE_FUNC_OVSDB(nb, TBL_NAME)
>> +
>>  /* Macro to define member functions of an engine node which represents
>>   * a table of open_vswitch DB */
>>  #define ENGINE_FUNC_OVS(TBL_NAME) \
>> @@ -360,6 +372,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void
> *data OVS_UNUSED) \
>>  #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
>>  ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
>>
>> +/* Macro to define an engine node which represents a table of OVN NB DB
> */
>> +#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
>> +ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
>> +
>>  /* Macro to define an engine node which represents a table of
> open_vswitch
>>   * DB */
>>  #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
>> diff --git a/northd/automake.mk b/northd/automake.mk
>> index 35ad8c09d9ba..f0c1fb11c83a 100644
>> --- a/northd/automake.mk
>> +++ b/northd/automake.mk
>> @@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
>> northd/northd.c \
>> northd/northd.h \
>> northd/ovn-northd.c \
>> +   northd/en-northd.c \
>> +   northd/en-northd.h \
>> +   northd/inc-proc-northd.c \
>> +   northd/inc-proc-northd.h \
>> northd/ipam.c \
>> northd/ipam.h
>>  northd_ovn_northd_LDADD = \
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> new file mode 100644
>> index 

Re: [ovs-dev] [PATCH ovn v3 1/7] inc-proc-eng: Allow definition of engine_node with global scope

2021-10-26 Thread Mark Gray
On 21/10/2021 06:24, Han Zhou wrote:
> On Mon, Oct 18, 2021 at 5:14 AM Mark Gray  wrote:
>>
>> Refactor ENGINE_NODE() macro to not assign function pointers. This
>> allows ENGINE_NODE() to be used outside functions, creating an
>> engine_node with global scope (but can be statically defined within a
> file).
>> This allows more flexibility in how the I-P engine can be used as
>> engine nodes can be defined. Allow this is not explicitly required for
>> I-P it does allow for a cleaner code base as the node definitions can
>> be kept together outside any functions.
>>
>> Additional function pointers (e.g. is_valid(), clear_tracked_data()),
>> may be assigned later, if required.
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  controller/ovn-controller.c | 2 +-
>>  lib/inc-proc-eng.h  | 8 
>>  2 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>> index 4202f32ccaf6..48121ccce082 100644
>> --- a/controller/ovn-controller.c
>> +++ b/controller/ovn-controller.c
>> @@ -3219,7 +3219,7 @@ main(int argc, char *argv[])
>>  stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
>>
>>  /* Define inc-proc-engine nodes. */
>> -ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones");
>> +ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones,
> "ct_zones");
>>  ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
>>  ENGINE_NODE(non_vif_data, "non_vif_data");
>>  ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
>> diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
>> index 859b30a71c86..1ccae559dff6 100644
>> --- a/lib/inc-proc-eng.h
>> +++ b/lib/inc-proc-eng.h
>> @@ -295,19 +295,19 @@ void engine_ovsdb_node_add_index(struct engine_node
> *, const char *name,
>>  .init = en_##NAME##_init, \
>>  .run = en_##NAME##_run, \
>>  .cleanup = en_##NAME##_cleanup, \
>> -.is_valid = en_##NAME##_is_valid, \
>> +.is_valid = NULL, \
>>  .clear_tracked_data = NULL, \
>>  };
>>
>>  #define ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
> 
> Thanks Mark. It took me a while to understand the macro again.
> ENGINE_NODE_CUSTOM_DATA was supposed to be used when is_valid is needed.
> Now that it is not the case anymore, and it becomes exactly the same as
> ENGINE_NODE, it can be removed.
> 
>>  ENGINE_NODE_DEF(NAME, NAME_STR)
>>
>> -#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
>> +#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(NAME,
> NAME_STR) \
> 
> CUSTOM and IS_VALID have the same meaning, so it may be simplified to
> ENGINE_NODE_WITH_CLEAR_TRACK_DATA_IS_VALID.
> 
>>  ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
> 
> Here we can use ENGINE_NODE instead of ENGINE_NODE_CUSTOM_DATA.
> 
> With this addressed:
> Acked-by: Han Zhou 

All this makes sense. Thanks

> 
>> -en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data;
>> +en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data; \
>> +en_##NAME.is_valid = en_##NAME##_is_valid;
>>
>>  #define ENGINE_NODE(NAME, NAME_STR) \
>> -static bool (*en_##NAME##_is_valid)(struct engine_node *node) =
> NULL; \
>>  ENGINE_NODE_DEF(NAME, NAME_STR)
>>
>>  #define ENGINE_NODE_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
>> --
>> 2.27.0
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2] ipsec: Update documentation for RHEL and CentOS

2021-10-26 Thread Mark Gray
Similarly to Fedora, we may also need to open firewall ports to enable
IPsec. Update the documentation to reflect this.

Signed-off-by: Mark Gray 
---

v2: Fix 0-day issue

 Documentation/tutorials/ovn-ipsec.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/tutorials/ovn-ipsec.rst 
b/Documentation/tutorials/ovn-ipsec.rst
index fa35eb84b316..305dd566dc22 100644
--- a/Documentation/tutorials/ovn-ipsec.rst
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -82,8 +82,8 @@ database to false::
 
 .. note::
 
-   On Fedora, you may need to install firewall rules to allow ESP and IKE
-   traffic::
+   On Fedora, RHEL and CentOS, you may need to install firewall rules to allow
+   ESP and IKE traffic::
 
# systemctl start firewalld
# firewall-cmd --add-service ipsec
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn] ipsec: Update documentation for RHEL and CentOS

2021-10-21 Thread Mark Gray
Similarly to Fedora, we may also need to open firewall ports to enable
IPsec. Update the documentation to reflect this.

Signed-off-by: Mark Gray 
---
 Documentation/tutorials/ovn-ipsec.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/tutorials/ovn-ipsec.rst 
b/Documentation/tutorials/ovn-ipsec.rst
index fa35eb84b316..a12edbf946bc 100644
--- a/Documentation/tutorials/ovn-ipsec.rst
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -82,7 +82,7 @@ database to false::
 
 .. note::
 
-   On Fedora, you may need to install firewall rules to allow ESP and IKE
+   On Fedora, RHEL and CentOS, you may need to install firewall rules to allow 
ESP and IKE
traffic::
 
# systemctl start firewalld
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ipsec: Update documentation for Fedora

2021-10-20 Thread Mark Gray
On 20/10/2021 16:00, Numan Siddique wrote:
> On Thu, Oct 14, 2021 at 9:22 AM Mark Gray  wrote:
>>
>> When running on Fedora, it may be necessary to allow ESP and IKE traffic
>> through the host firewall. If not, this will result in ICMP host
>> unreachable messages:
>>
>> 13:52:10.000695 IP 192.168.122.228 > 192.168.122.125: 
>> ESP(spi=0xa5830a6b,seq=0x2), length 156
>> 13:52:10.000721 IP 192.168.122.228 > 192.168.122.125: 
>> ESP(spi=0xa5830a6b,seq=0x2), length 156
>> 13:52:10.000864 IP 192.168.122.125 > 192.168.122.228: ICMP host 
>> 192.168.122.125 unreachable - admin prohibited filter, length 184
>> 13:52:10.000874 IP 192.168.122.125 > 192.168.122.228: ICMP host 
>> 192.168.122.125 unreachable - admin prohibited filter, length 184
>>
>> This commit updates the documentation to reflect this.
>>
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2002278
>> Signed-off-by: Mark Gray 
> 
> Thanks.   I applied to the main branch.
> 

Thanks

> Numan
> 
>> ---
>>  Documentation/tutorials/ovn-ipsec.rst | 13 +
>>  1 file changed, 13 insertions(+)
>>
>> diff --git a/Documentation/tutorials/ovn-ipsec.rst 
>> b/Documentation/tutorials/ovn-ipsec.rst
>> index 3adef68bb697..fa35eb84b316 100644
>> --- a/Documentation/tutorials/ovn-ipsec.rst
>> +++ b/Documentation/tutorials/ovn-ipsec.rst
>> @@ -80,6 +80,19 @@ database to false::
>>
>>  $ ovn-nbctl set nb_global . ipsec=false
>>
>> +.. note::
>> +
>> +   On Fedora, you may need to install firewall rules to allow ESP and IKE
>> +   traffic::
>> +
>> +   # systemctl start firewalld
>> +   # firewall-cmd --add-service ipsec
>> +
>> +   Or to make permanent::
>> +
>> +   # systemctl enable firewalld
>> +   # firewall-cmd --permanent --add-service ipsec
>> +
>>  Troubleshooting
>>  ---
>>
>> --
>> 2.27.0
>>
>> ___
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn 0/7] northd: Introduce incremental processing framework

2021-10-18 Thread Mark Gray
On 18/10/2021 11:03, Mark Gray wrote:
> On 16/10/2021 02:21, Han Zhou wrote:
>> On Wed, Sep 29, 2021 at 10:23 AM Mark Gray  wrote:
>>>
>>> Add the 'inc-proc-eng' framework to northd. This does *not*
>>> add any incremental processing at this stage but provides the
>>> framework to do so. Even in this base configuration, we see an
>>> advantage as northd no longer processes the databases if it has
>>> been woken only to handle, for example, a unixctl command. This
>>> can be seen below
>>>
>>> $ ovn-appctl -t ovn-northd stopwatch/reset
>>> $ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show
>>> /dev/null; done
>>> $ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
>>> Statistics for 'ovnnb_db_run'
>>>   Total samples: 0
>>>   Maximum: 0 msec
>>>   Minimum: 0 msec
>>>   95th percentile: 0.00 msec
>>>   Short term average: 0.00 msec
>>>   Long term average: 0.00 msec
>>>
>>> Hopefully this starting point will allow others to discuss or contribute
>>> changes to incrementally process some aspects of northd. We an also
>>> decide if it is worth progressing with this in general.
>>>
>>> Thanks,
>>>
>>> Mark Gray (7):
>>>   inc-proc-eng: Allow definition of engine_node with global scope
>>>   northd: Introduce incremental processing for northd
>>>   northd: Add n_nat_entries field to 'struct ovn_datapath'
>>>   northd: Rename struct northd_context
>>
>> Hi Mark,
>>
>> Sorry for the slow response, but I encountered a problem when applying the
>> series at the 4th patch:
>>
>> Applying: northd: Rename struct northd_context
>> error: sha1 information is lacking or useless (northd/northd.c).
>> error: could not build fake ancestor
>>
>> Could you check on your side if it applies cleanly on the current main
>> branch?
>>
> 
> Hi Han,
> 
> It did need a rebase but I don't think that is the cause of your error.
> Your error looks like the patches were being applied before ovn-northd.c
> was renamed to northd.c? Regardless, I did the rebase and tested. The
> new version can be found at
> https://patchwork.ozlabs.org/project/ovn/list/?series=267610 :

This ^ version has a compile error in 2/7 which caused 0-day to fail.
This, below, is an updated series that fixes that:

https://patchwork.ozlabs.org/project/ovn/list/?series=267648

> 
> $ git log --format=oneline -1
> 3a597e03cd411e8316b68e13f88f1b097ad82ba0 (HEAD -> main, upstream/main)
> controller: do not mark bfd and ipv6_pd msgs as local-only
> 
> $ git checkout -b test
> Switched to a new branch 'test'
> 
> $ git-pw series apply 267610
> Server version missing
> You should provide the server version in the URL configured via
> git-config or --server
> This will be required in git-pw 2.0
> Applying: inc-proc-eng: Allow definition of engine_node with global scope
> Applying: northd: Introduce incremental processing for northd
> Applying: northd: Add n_nat_entries field to 'struct ovn_datapath'
> Applying: northd: Rename struct northd_context
> Applying: northd: Introduce struct northd_data
> Applying: northd: Add lflow node
> Applying: en_lflow: Generate logical flows
> 
> 
>> Thanks,
>> Han
>>
>>>   northd: Introduce struct northd_data
>>>   northd: Add lflow node
>>>   en_lflow: Generate logical flows
>>>
>>>  controller/ovn-controller.c |   2 +-
>>>  lib/inc-proc-eng.h  |  24 ++-
>>>  northd/automake.mk  |   6 +
>>>  northd/en-lflow.c   |  54 ++
>>>  northd/en-lflow.h   |  16 ++
>>>  northd/en-northd.c  |  65 +++
>>>  northd/en-northd.h  |  21 +++
>>>  northd/inc-proc-northd.c| 257 ++
>>>  northd/inc-proc-northd.h|  15 ++
>>>  northd/northd.c | 358 +++-
>>>  northd/northd.h |  36 +++-
>>>  northd/ovn-northd.c | 237 ++--
>>>  12 files changed, 807 insertions(+), 284 deletions(-)
>>>  create mode 100644 northd/en-lflow.c
>>>  create mode 100644 northd/en-lflow.h
>>>  create mode 100644 northd/en-northd.c
>>>  create mode 100644 northd/en-northd.h
>>>  create mode 100644 northd/inc-proc-northd.c
>>>  create mode 100644 northd/inc-proc-northd.h
>>>
>>> --
>>> 2.27.0
>>>
>>>
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v3 6/7] northd: Add lflow node

2021-10-18 Thread Mark Gray
Add an additional node that initially does nothing. This serves as a
template for how to add a new node. This node is inserted after
the northd_node.

This node will be updated in a later commit to generate logical
flows for the SBDB.

Signed-off-by: Mark Gray 
---
 northd/automake.mk   |  2 ++
 northd/en-lflow.c| 42 
 northd/en-lflow.h| 16 +++
 northd/inc-proc-northd.c |  5 -
 northd/northd.c  |  2 --
 5 files changed, 64 insertions(+), 3 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h

diff --git a/northd/automake.mk b/northd/automake.mk
index f0c1fb11c83a..4862ec7b7ff3 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -6,6 +6,8 @@ northd_ovn_northd_SOURCES = \
northd/ovn-northd.c \
northd/en-northd.c \
northd/en-northd.h \
+   northd/en-lflow.c \
+   northd/en-lflow.h \
northd/inc-proc-northd.c \
northd/inc-proc-northd.h \
northd/ipam.c \
diff --git a/northd/en-lflow.c b/northd/en-lflow.c
new file mode 100644
index ..46072cb0162e
--- /dev/null
+++ b/northd/en-lflow.c
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-lflow.h"
+#include "en-northd.h"
+
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_lflow);
+
+void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+engine_set_node_state(node, EN_UPDATED);
+}
+void *en_lflow_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+return NULL;
+}
+
+void en_lflow_cleanup(void *data OVS_UNUSED)
+{
+}
diff --git a/northd/en-lflow.h b/northd/en-lflow.h
new file mode 100644
index ..0e4d522ff3fe
--- /dev/null
+++ b/northd/en-lflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_LFLOW_H
+#define EN_LFLOW_H 1
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "lib/inc-proc-eng.h"
+
+void en_lflow_run(struct engine_node *node, void *data);
+void *en_lflow_init(struct engine_node *node, struct engine_arg *arg);
+void en_lflow_cleanup(void *data);
+
+#endif /* EN_LFLOW_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 572b8de6536a..519fc1d0cb46 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -25,6 +25,7 @@
 #include "openvswitch/vlog.h"
 #include "inc-proc-northd.h"
 #include "en-northd.h"
+#include "en-lflow.h"
 #include "util.h"
 
 VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
@@ -140,6 +141,7 @@ enum sb_engine_node {
 /* Define engine nodes for other nodes. They should be defined as static to
  * avoid sparse errors. */
 static ENGINE_NODE(northd, "northd");
+static ENGINE_NODE(lflow, "lflow");
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb)
@@ -204,13 +206,14 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_add_input(_northd, _sb_load_balancer, NULL);
 engine_add_input(_northd, _sb_bfd, NULL);
 engine_add_input(_northd, _sb_fdb, NULL);
+engine_add_input(_lflow, _northd, NULL);
 
 struct engine_arg engine_arg = {
 .nb_idl = nb->idl,
 .sb_idl = sb->idl,
 };
 
-engine_init(_northd, _arg);
+engine_init(_lflow, _arg);
 }
 
 void inc_proc_northd_run(struct northd_idl_context *ctx,
diff --git a/northd/northd.c b/northd/northd.c
index 6426fcbe1215..e1097e6b301a 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -12974,7 +12974,6 @@ struct lflows_thread_pool {
 struct worker_pool *pool;
 };
 
-
 static void *
 build_lflows_thread(void *arg)
 {
@@ -14556,7 +14555,6 @@ ovnnb_db_run(struct northd_data *data,
 cleanup_stale_fdp_entries(ctx, >datapaths);
 bfd_cleanup_connections(ctx, >bfd_connections);
 stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-
 }
 
 /* Stores the list of chassis which references an ha_chassis_group.
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v3 5/7] northd: Introduce struct northd_data

2021-10-18 Thread Mark Gray
'struct northd_data' is used to hold the output data from the
incremental processing node 'en_northd'. This will be used, in
a later commit, as the input data to 'en_lflow'. In order to achieve
this, we refactor in the following way:

* Introduce northd_init() which initializes this data.
* Introduce northd_destroy() which clears this data for a new iteration.
* Introduce northd_indices_create() which does a one-time creation of
  indices for number of tables needed by northd.
* Remove 'ovn_internal_version' from the context passed to northd
  as it can be determined within northd using ovn_get_internal_version.
* Remove 'use_parallel_build' from the context passed to northd
  as it can be determined within northd using can_parallelize_hashes().
* Refactor northd.c to use 'struct northd_data' where applicable.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c  |  28 -
 northd/en-northd.h  |   4 +
 northd/northd.c | 278 
 northd/northd.h |  28 -
 northd/ovn-northd.c |  28 +
 5 files changed, 204 insertions(+), 162 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index 8dec51535af0..1b206521e152 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -20,26 +20,46 @@
 
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
+#include "openvswitch/list.h" /* TODO This is needed for ovn-parallel-hmap.h.
+   * lib/ovn-parallel-hmap.h should be updated
+   * to include this dependency itself */
+#include "lib/ovn-parallel-hmap.h"
 #include "northd.h"
+#include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
 
-void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+void en_northd_run(struct engine_node *node, void *data)
 {
 const struct engine_context *eng_ctx = engine_get_context();
 struct northd_idl_context *ctx = eng_ctx->client_ctx;
-ovn_db_run(ctx);
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
 
+northd_destroy(northd_data);
+northd_init(northd_data);
+
+northd_run(ctx, northd_data);
 engine_set_node_state(node, EN_UPDATED);
 
 }
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
- struct engine_arg *arg OVS_UNUSED)
+ struct engine_arg *arg)
 {
-return NULL;
+struct ed_type_northd *data = xmalloc(sizeof *data);
+data->data = xmalloc(sizeof *data->data);
+
+data->data->use_parallel_build = can_parallelize_hashes(false);
+northd_indices_create(data->data, arg->sb_idl);
+northd_init(data->data);
+
+return data;
 }
 
 void en_northd_cleanup(void *data OVS_UNUSED)
 {
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
+
+northd_destroy(northd_data);
+free(northd_data);
 }
diff --git a/northd/en-northd.h b/northd/en-northd.h
index 0e7f76245e69..da386298d821 100644
--- a/northd/en-northd.h
+++ b/northd/en-northd.h
@@ -9,6 +9,10 @@
 
 #include "lib/inc-proc-eng.h"
 
+struct ed_type_northd {
+struct northd_data *data;
+};
+
 void en_northd_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED);
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
  struct engine_arg *arg);
diff --git a/northd/northd.c b/northd/northd.c
index d61368c1e406..6426fcbe1215 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -2950,6 +2950,7 @@ chassis_group_list_changed(
 
 static void
 sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
+   struct northd_data *data,
const struct nbrec_ha_chassis_group *nb_ha_grp,
struct ovsdb_idl_index *sbrec_chassis_by_name,
const struct sbrec_port_binding *pb)
@@ -2957,7 +2958,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 bool new_sb_chassis_group = false;
 const struct sbrec_ha_chassis_group *sb_ha_grp =
 ha_chassis_group_lookup_by_name(
-ctx->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
+data->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
 
 if (!sb_ha_grp) {
 sb_ha_grp = sbrec_ha_chassis_group_insert(ctx->ovnsb_txn);
@@ -3003,6 +3004,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 static void
 copy_gw_chassis_from_nbrp_to_sbpb(
 struct northd_idl_context *ctx,
+struct northd_data *data,
 struct ovsdb_idl_index *sbrec_chassis_by_name,
 const struct nbrec_logical_router_port *lrp,
 const struct sbrec_port_binding *port_binding)
@@ -3012,7 +3014,7 @@ copy_gw_chassis_from_nbrp_to_sbpb(
  * for the distributed gateway router port. */
 const struct sbrec_ha_chassis_group *sb_ha_chassis_gr

[ovs-dev] [PATCH ovn v3 7/7] en_lflow: Generate logical flows

2021-10-18 Thread Mark Gray
Generate logical flows using 'en_flow' incremental processing node.
This node uses output data from 'en_northd' in order to generate
logical flows.

Signed-off-by: Mark Gray 
---
 northd/en-lflow.c | 12 
 northd/northd.c   |  6 +-
 northd/northd.h   |  1 +
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/northd/en-lflow.c b/northd/en-lflow.c
index 46072cb0162e..e24c00e039c3 100644
--- a/northd/en-lflow.c
+++ b/northd/en-lflow.c
@@ -23,12 +23,24 @@
 
 #include "lib/inc-proc-eng.h"
 #include "northd.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
+#include "timeval.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_lflow);
 
 void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
 {
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
+
+struct ed_type_northd *northd_data = engine_get_input_data("northd", node);
+
+stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+build_lflows(ctx, northd_data->data);
+stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+
 engine_set_node_state(node, EN_UPDATED);
 }
 void *en_lflow_init(struct engine_node *node OVS_UNUSED,
diff --git a/northd/northd.c b/northd/northd.c
index e1097e6b301a..03f321ba63df 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -13327,8 +13327,7 @@ static bool reset_parallel = false;
 
 /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database,
  * constructing their contents based on the OVN_NB database. */
-static void
-build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
 {
 struct hmap lflows;
 
@@ -14542,9 +14541,6 @@ ovnnb_db_run(struct northd_data *data,
 build_meter_groups(ctx, >meter_groups);
 build_bfd_table(ctx, >bfd_connections, >ports);
 stopwatch_stop(BUILD_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
-build_lflows(ctx, data);
-stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
 stopwatch_start(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
 ovn_update_ipv6_prefix(>ports);
 
diff --git a/northd/northd.h b/northd/northd.h
index d4bc5cf16541..07ea6899984f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -51,5 +51,6 @@ void northd_destroy(struct northd_data *data);
 void northd_init(struct northd_data *data);
 void northd_indices_create(struct northd_data *data,
struct ovsdb_idl *ovnsb_idl);
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data);
 
 #endif /* NORTHD_H */
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v3 4/7] northd: Rename struct northd_context

2021-10-18 Thread Mark Gray
In order to prepare for a subsequent commit, rename
'struct northd_context' to 'struct northd_idl_context'. In
subsequent commits, 'struct northd_idl_context' will then be
used, only, to hold the IDL context required by northd.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c   |  2 +-
 northd/inc-proc-northd.c |  2 +-
 northd/inc-proc-northd.h |  2 +-
 northd/northd.c  | 89 
 northd/northd.h  |  4 +-
 northd/ovn-northd.c  | 10 ++---
 6 files changed, 55 insertions(+), 54 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index d310fa4dd31f..8dec51535af0 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -28,7 +28,7 @@ VLOG_DEFINE_THIS_MODULE(en_northd);
 void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
 {
 const struct engine_context *eng_ctx = engine_get_context();
-struct northd_context *ctx = eng_ctx->client_ctx;
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
 ovn_db_run(ctx);
 
 engine_set_node_state(node, EN_UPDATED);
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 85baeb07d3d9..572b8de6536a 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -213,7 +213,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_init(_northd, _arg);
 }
 
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute) {
 engine_set_force_recompute(recompute);
 engine_init_run();
diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
index 09cb8f3b3a80..6ee056dc14f5 100644
--- a/northd/inc-proc-northd.h
+++ b/northd/inc-proc-northd.h
@@ -8,7 +8,7 @@
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb);
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute);
 void inc_proc_northd_cleanup(void);
 
diff --git a/northd/northd.c b/northd/northd.c
index 9e84ee6310a9..d61368c1e406 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -1256,7 +1256,7 @@ ovn_datapath_update_external_ids(struct ovn_datapath *od)
 }
 
 static void
-join_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+join_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
struct ovs_list *sb_only, struct ovs_list *nb_only,
struct ovs_list *both, struct ovs_list *lr_list)
 {
@@ -1367,7 +1367,7 @@ is_vxlan_mode(struct ovsdb_idl *ovnsb_idl)
 }
 
 static uint32_t
-get_ovn_max_dp_key_local(struct northd_context *ctx)
+get_ovn_max_dp_key_local(struct northd_idl_context *ctx)
 {
 if (is_vxlan_mode(ctx->ovnsb_idl)) {
 /* OVN_MAX_DP_GLOBAL_NUM doesn't apply for vxlan mode. */
@@ -1377,7 +1377,7 @@ get_ovn_max_dp_key_local(struct northd_context *ctx)
 }
 
 static void
-ovn_datapath_allocate_key(struct northd_context *ctx,
+ovn_datapath_allocate_key(struct northd_idl_context *ctx,
   struct hmap *datapaths, struct hmap *dp_tnlids,
   struct ovn_datapath *od, uint32_t *hint)
 {
@@ -1397,7 +1397,7 @@ ovn_datapath_allocate_key(struct northd_context *ctx,
 }
 
 static void
-ovn_datapath_assign_requested_tnl_id(struct northd_context *ctx,
+ovn_datapath_assign_requested_tnl_id(struct northd_idl_context *ctx,
  struct hmap *dp_tnlids,
  struct ovn_datapath *od)
 {
@@ -1431,7 +1431,7 @@ ovn_datapath_assign_requested_tnl_id(struct 
northd_context *ctx,
  * Initializes 'datapaths' to contain a "struct ovn_datapath" for every logical
  * switch and router. */
 static void
-build_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+build_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
 struct ovs_list *lr_list)
 {
 struct ovs_list sb_only, nb_only, both;
@@ -2402,7 +2402,7 @@ tag_alloc_create_new_tag(struct hmap *tag_alloc_table,
 
 
 static void
-join_logical_ports(struct northd_context *ctx,
+join_logical_ports(struct northd_idl_context *ctx,
struct hmap *datapaths, struct hmap *ports,
struct hmap *chassis_qdisc_queues,
struct hmap *tag_alloc_table, struct ovs_list *sb_only,
@@ -2864,7 +2864,7 @@ sbpb_gw_chassis_needs_update(
 }
 
 static struct sbrec_ha_chassis *
-create_sb_ha_chassis(struct northd_context *ctx,
+create_sb_ha_chassis(struct northd_idl_context *ctx,
  const struct sbrec_chassis *chassis,
  const char *chassis_name, int priority)
 {
@@ -2949,7 +2949,7 @@ chassis_group_list_changed(
 }
 
 static void
-sync_ha_chassis_group_for_sbpb(struct northd_context *ctx,
+sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
 

[ovs-dev] [PATCH ovn v3 2/7] northd: Introduce incremental processing for northd

2021-10-18 Thread Mark Gray
Initial implementation adds a single node (northd). This single
node executes the northd processing pipeline but does not do so
incrementally.

In order to develop incremental processing for northd, the code
will be organised with a .c/.h file for each I-P node following
the naming convention en-.c/.h. These files will
contain definition of the node data, the main node processing
functions and change handlers (if any). The purpose of these nodes
will be coordination of the nodes work and implemention of the
relevant interfaces to plugin to the I-P framework. The actual
work that will be executed by the node will be organised into
a companion file or files. Ideally this file will follow the
naming convention of the node: e.g. en-.c is
associated with .c.

Initial node topology sees the northd node dependent on all DB
nodes. This will evolve over time.

Co-authored-by: Numan Siddique 
Signed-off-by: Numan Siddique 
Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  16 +++
 northd/automake.mk   |   4 +
 northd/en-northd.c   |  45 +++
 northd/en-northd.h   |  17 +++
 northd/inc-proc-northd.c | 254 +++
 northd/inc-proc-northd.h |  15 +++
 northd/northd.c  |  12 +-
 northd/northd.h  |   9 +-
 northd/ovn-northd.c  | 201 ---
 9 files changed, 490 insertions(+), 83 deletions(-)
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 1ccae559dff6..a3f5a7e64287 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -63,15 +63,22 @@
 #define ENGINE_MAX_INPUT 256
 #define ENGINE_MAX_OVSDB_INDEX 256
 
+#include 
+#include 
+
+#include "compiler.h"
+
 struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
+struct ovsdb_idl_txn *ovnnb_idl_txn;
 void *client_ctx;
 };
 
 /* Arguments to be passed to the engine at engine_init(). */
 struct engine_arg {
 struct ovsdb_idl *sb_idl;
+struct ovsdb_idl *nb_idl;
 struct ovsdb_idl *ovs_idl;
 };
 
@@ -347,6 +354,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_FUNC_SB(TBL_NAME) \
 ENGINE_FUNC_OVSDB(sb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN NB DB */
+#define ENGINE_FUNC_NB(TBL_NAME) \
+ENGINE_FUNC_OVSDB(nb, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -360,6 +372,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
 ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
 
+/* Macro to define an engine node which represents a table of OVN NB DB */
+#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
+ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
diff --git a/northd/automake.mk b/northd/automake.mk
index 35ad8c09d9ba..f0c1fb11c83a 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
northd/northd.c \
northd/northd.h \
northd/ovn-northd.c \
+   northd/en-northd.c \
+   northd/en-northd.h \
+   northd/inc-proc-northd.c \
+   northd/inc-proc-northd.h \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/en-northd.c b/northd/en-northd.c
new file mode 100644
index ..d310fa4dd31f
--- /dev/null
+++ b/northd/en-northd.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-northd.h"
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_northd);
+
+void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_context *ctx = eng_ctx->client_ctx;
+ovn_db_run(ctx);
+
+engine_set_node_state(node, EN_UPDATED);

[ovs-dev] [PATCH ovn v3 3/7] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-10-18 Thread Mark Gray
destroy_nat_entries() iterates over nat_entries using 'n_nat'
as the number of NAT entries from the NB database. This behaviour can be
incorrect as it assumes that there are 'n_nat' 'nat_entries'. 'struct
ovn_datapath' should maintain a count of 'nat_entries' in 'struct
ovn_datapath' rather than read the value from NBDB IDL to properly
account for the number of 'nat_entries'.

This issue becomes appatent when using destroy_nat_entries()
as part of an incremental processing loop:

Consider an example in which we have completed iteration x, and
started iteration x+1. If we add a NAT entry to NBDB between iteration x
and iteration x+1, od->nbr->n_nat will contain the updated value of
n_nat as the northbound record will have been updated. However, if
we do not (re)initialized the nat entries in od, od->n_nat_entries
could be equal to the previous value. This can cause destroy_nat_entries()
to loop over the wrong number of 'nat_entries' causing unexpected
behaviour.

Signed-off-by: Mark Gray 
---
 northd/northd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/northd/northd.c b/northd/northd.c
index 1321e26faa9d..9e84ee6310a9 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -603,6 +603,8 @@ struct ovn_datapath {
 
 /* NAT entries configured on the router. */
 struct ovn_nat *nat_entries;
+size_t n_nat_entries;
+
 bool has_distributed_nat;
 
 /* Set of nat external ips on the router. */
@@ -787,6 +789,7 @@ init_nat_entries(struct ovn_datapath *od)
 od->has_distributed_nat = true;
 }
 }
+od->n_nat_entries = od->nbr->n_nat;
 }
 
 static void
@@ -800,7 +803,7 @@ destroy_nat_entries(struct ovn_datapath *od)
 destroy_lport_addresses(>dnat_force_snat_addrs);
 destroy_lport_addresses(>lb_force_snat_addrs);
 
-for (size_t i = 0; i < od->nbr->n_nat; i++) {
+for (size_t i = 0; i < od->n_nat_entries; i++) {
 destroy_lport_addresses(>nat_entries[i].ext_addrs);
 }
 }
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v3 1/7] inc-proc-eng: Allow definition of engine_node with global scope

2021-10-18 Thread Mark Gray
Refactor ENGINE_NODE() macro to not assign function pointers. This
allows ENGINE_NODE() to be used outside functions, creating an
engine_node with global scope (but can be statically defined within a file).
This allows more flexibility in how the I-P engine can be used as
engine nodes can be defined. Allow this is not explicitly required for
I-P it does allow for a cleaner code base as the node definitions can
be kept together outside any functions.

Additional function pointers (e.g. is_valid(), clear_tracked_data()),
may be assigned later, if required.

Signed-off-by: Mark Gray 
---
 controller/ovn-controller.c | 2 +-
 lib/inc-proc-eng.h  | 8 
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 4202f32ccaf6..48121ccce082 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -3219,7 +3219,7 @@ main(int argc, char *argv[])
 stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
 
 /* Define inc-proc-engine nodes. */
-ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones");
+ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones, "ct_zones");
 ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
 ENGINE_NODE(non_vif_data, "non_vif_data");
 ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 859b30a71c86..1ccae559dff6 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -295,19 +295,19 @@ void engine_ovsdb_node_add_index(struct engine_node *, 
const char *name,
 .init = en_##NAME##_init, \
 .run = en_##NAME##_run, \
 .cleanup = en_##NAME##_cleanup, \
-.is_valid = en_##NAME##_is_valid, \
+.is_valid = NULL, \
 .clear_tracked_data = NULL, \
 };
 
 #define ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
-#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
+#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(NAME, NAME_STR) \
 ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
-en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data;
+en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data; \
+en_##NAME.is_valid = en_##NAME##_is_valid;
 
 #define ENGINE_NODE(NAME, NAME_STR) \
-static bool (*en_##NAME##_is_valid)(struct engine_node *node) = NULL; \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
 #define ENGINE_NODE_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v3 0/7] northd: Introduce incremental processing framework

2021-10-18 Thread Mark Gray
Add the 'inc-proc-eng' framework to northd. This does *not*
add any incremental processing at this stage but provides the
framework to do so. Even in this base configuration, we see an
advantage as northd no longer processes the databases if it has
been woken only to handle, for example, a unixctl command. This
can be seen below

$ ovn-appctl -t ovn-northd stopwatch/reset
$ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show >/dev/null; done
$ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Statistics for 'ovnnb_db_run'
  Total samples: 0
  Maximum: 0 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 0.00 msec
  Long term average: 0.00 msec

Hopefully this starting point will allow others to discuss or contribute
changes to incrementally process some aspects of northd. We an also
decide if it is worth progressing with this in general.

Thanks,

v2: Rebase
v3: Fix compile error in 2/7 picked up by 0-day robot

Mark Gray (7):
  inc-proc-eng: Allow definition of engine_node with global scope
  northd: Introduce incremental processing for northd
  northd: Add n_nat_entries field to 'struct ovn_datapath'
  northd: Rename struct northd_context
  northd: Introduce struct northd_data
  northd: Add lflow node
  en_lflow: Generate logical flows

 controller/ovn-controller.c |   2 +-
 lib/inc-proc-eng.h  |  24 ++-
 northd/automake.mk  |   6 +
 northd/en-lflow.c   |  54 ++
 northd/en-lflow.h   |  16 ++
 northd/en-northd.c  |  65 +++
 northd/en-northd.h  |  21 ++
 northd/inc-proc-northd.c| 257 +
 northd/inc-proc-northd.h|  15 ++
 northd/northd.c | 368 +++-
 northd/northd.h |  36 +++-
 northd/ovn-northd.c | 237 +--
 12 files changed, 812 insertions(+), 289 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

-- 
2.27.0


___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn 0/7] northd: Introduce incremental processing framework

2021-10-18 Thread Mark Gray
On 16/10/2021 02:21, Han Zhou wrote:
> On Wed, Sep 29, 2021 at 10:23 AM Mark Gray  wrote:
>>
>> Add the 'inc-proc-eng' framework to northd. This does *not*
>> add any incremental processing at this stage but provides the
>> framework to do so. Even in this base configuration, we see an
>> advantage as northd no longer processes the databases if it has
>> been woken only to handle, for example, a unixctl command. This
>> can be seen below
>>
>> $ ovn-appctl -t ovn-northd stopwatch/reset
>> $ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show
>> /dev/null; done
>> $ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
>> Statistics for 'ovnnb_db_run'
>>   Total samples: 0
>>   Maximum: 0 msec
>>   Minimum: 0 msec
>>   95th percentile: 0.00 msec
>>   Short term average: 0.00 msec
>>   Long term average: 0.00 msec
>>
>> Hopefully this starting point will allow others to discuss or contribute
>> changes to incrementally process some aspects of northd. We an also
>> decide if it is worth progressing with this in general.
>>
>> Thanks,
>>
>> Mark Gray (7):
>>   inc-proc-eng: Allow definition of engine_node with global scope
>>   northd: Introduce incremental processing for northd
>>   northd: Add n_nat_entries field to 'struct ovn_datapath'
>>   northd: Rename struct northd_context
> 
> Hi Mark,
> 
> Sorry for the slow response, but I encountered a problem when applying the
> series at the 4th patch:
> 
> Applying: northd: Rename struct northd_context
> error: sha1 information is lacking or useless (northd/northd.c).
> error: could not build fake ancestor
> 
> Could you check on your side if it applies cleanly on the current main
> branch?
> 

Hi Han,

It did need a rebase but I don't think that is the cause of your error.
Your error looks like the patches were being applied before ovn-northd.c
was renamed to northd.c? Regardless, I did the rebase and tested. The
new version can be found at
https://patchwork.ozlabs.org/project/ovn/list/?series=267610 :

$ git log --format=oneline -1
3a597e03cd411e8316b68e13f88f1b097ad82ba0 (HEAD -> main, upstream/main)
controller: do not mark bfd and ipv6_pd msgs as local-only

$ git checkout -b test
Switched to a new branch 'test'

$ git-pw series apply 267610
Server version missing
You should provide the server version in the URL configured via
git-config or --server
This will be required in git-pw 2.0
Applying: inc-proc-eng: Allow definition of engine_node with global scope
Applying: northd: Introduce incremental processing for northd
Applying: northd: Add n_nat_entries field to 'struct ovn_datapath'
Applying: northd: Rename struct northd_context
Applying: northd: Introduce struct northd_data
Applying: northd: Add lflow node
Applying: en_lflow: Generate logical flows


> Thanks,
> Han
> 
>>   northd: Introduce struct northd_data
>>   northd: Add lflow node
>>   en_lflow: Generate logical flows
>>
>>  controller/ovn-controller.c |   2 +-
>>  lib/inc-proc-eng.h  |  24 ++-
>>  northd/automake.mk  |   6 +
>>  northd/en-lflow.c   |  54 ++
>>  northd/en-lflow.h   |  16 ++
>>  northd/en-northd.c  |  65 +++
>>  northd/en-northd.h  |  21 +++
>>  northd/inc-proc-northd.c| 257 ++
>>  northd/inc-proc-northd.h|  15 ++
>>  northd/northd.c | 358 +++-
>>  northd/northd.h |  36 +++-
>>  northd/ovn-northd.c | 237 ++--
>>  12 files changed, 807 insertions(+), 284 deletions(-)
>>  create mode 100644 northd/en-lflow.c
>>  create mode 100644 northd/en-lflow.h
>>  create mode 100644 northd/en-northd.c
>>  create mode 100644 northd/en-northd.h
>>  create mode 100644 northd/inc-proc-northd.c
>>  create mode 100644 northd/inc-proc-northd.h
>>
>> --
>> 2.27.0
>>
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2 5/7] northd: Introduce struct northd_data

2021-10-18 Thread Mark Gray
'struct northd_data' is used to hold the output data from the
incremental processing node 'en_northd'. This will be used, in
a later commit, as the input data to 'en_lflow'. In order to achieve
this, we refactor in the following way:

* Introduce northd_init() which initializes this data.
* Introduce northd_destroy() which clears this data for a new iteration.
* Introduce northd_indices_create() which does a one-time creation of
  indices for number of tables needed by northd.
* Remove 'ovn_internal_version' from the context passed to northd
  as it can be determined within northd using ovn_get_internal_version.
* Remove 'use_parallel_build' from the context passed to northd
  as it can be determined within northd using can_parallelize_hashes().
* Refactor northd.c to use 'struct northd_data' where applicable.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c  |  28 -
 northd/en-northd.h  |   4 +
 northd/northd.c | 278 
 northd/northd.h |  27 -
 northd/ovn-northd.c |  28 +
 5 files changed, 204 insertions(+), 161 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index 8dec51535af0..1b206521e152 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -20,26 +20,46 @@
 
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
+#include "openvswitch/list.h" /* TODO This is needed for ovn-parallel-hmap.h.
+   * lib/ovn-parallel-hmap.h should be updated
+   * to include this dependency itself */
+#include "lib/ovn-parallel-hmap.h"
 #include "northd.h"
+#include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
 
-void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+void en_northd_run(struct engine_node *node, void *data)
 {
 const struct engine_context *eng_ctx = engine_get_context();
 struct northd_idl_context *ctx = eng_ctx->client_ctx;
-ovn_db_run(ctx);
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
 
+northd_destroy(northd_data);
+northd_init(northd_data);
+
+northd_run(ctx, northd_data);
 engine_set_node_state(node, EN_UPDATED);
 
 }
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
- struct engine_arg *arg OVS_UNUSED)
+ struct engine_arg *arg)
 {
-return NULL;
+struct ed_type_northd *data = xmalloc(sizeof *data);
+data->data = xmalloc(sizeof *data->data);
+
+data->data->use_parallel_build = can_parallelize_hashes(false);
+northd_indices_create(data->data, arg->sb_idl);
+northd_init(data->data);
+
+return data;
 }
 
 void en_northd_cleanup(void *data OVS_UNUSED)
 {
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
+
+northd_destroy(northd_data);
+free(northd_data);
 }
diff --git a/northd/en-northd.h b/northd/en-northd.h
index 0e7f76245e69..da386298d821 100644
--- a/northd/en-northd.h
+++ b/northd/en-northd.h
@@ -9,6 +9,10 @@
 
 #include "lib/inc-proc-eng.h"
 
+struct ed_type_northd {
+struct northd_data *data;
+};
+
 void en_northd_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED);
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
  struct engine_arg *arg);
diff --git a/northd/northd.c b/northd/northd.c
index d61368c1e406..6426fcbe1215 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -2950,6 +2950,7 @@ chassis_group_list_changed(
 
 static void
 sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
+   struct northd_data *data,
const struct nbrec_ha_chassis_group *nb_ha_grp,
struct ovsdb_idl_index *sbrec_chassis_by_name,
const struct sbrec_port_binding *pb)
@@ -2957,7 +2958,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 bool new_sb_chassis_group = false;
 const struct sbrec_ha_chassis_group *sb_ha_grp =
 ha_chassis_group_lookup_by_name(
-ctx->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
+data->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
 
 if (!sb_ha_grp) {
 sb_ha_grp = sbrec_ha_chassis_group_insert(ctx->ovnsb_txn);
@@ -3003,6 +3004,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 static void
 copy_gw_chassis_from_nbrp_to_sbpb(
 struct northd_idl_context *ctx,
+struct northd_data *data,
 struct ovsdb_idl_index *sbrec_chassis_by_name,
 const struct nbrec_logical_router_port *lrp,
 const struct sbrec_port_binding *port_binding)
@@ -3012,7 +3014,7 @@ copy_gw_chassis_from_nbrp_to_sbpb(
  * for the distributed gateway router port. */
 const struct sbrec_ha_chassis_group *sb_ha_chassis_gr

[ovs-dev] [PATCH ovn v2 6/7] northd: Add lflow node

2021-10-18 Thread Mark Gray
Add an additional node that initially does nothing. This serves as a
template for how to add a new node. This node is inserted after
the northd_node.

This node will be updated in a later commit to generate logical
flows for the SBDB.

Signed-off-by: Mark Gray 
---
 northd/automake.mk   |  2 ++
 northd/en-lflow.c| 42 
 northd/en-lflow.h| 16 +++
 northd/inc-proc-northd.c |  5 -
 northd/northd.c  |  2 --
 5 files changed, 64 insertions(+), 3 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h

diff --git a/northd/automake.mk b/northd/automake.mk
index f0c1fb11c83a..4862ec7b7ff3 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -6,6 +6,8 @@ northd_ovn_northd_SOURCES = \
northd/ovn-northd.c \
northd/en-northd.c \
northd/en-northd.h \
+   northd/en-lflow.c \
+   northd/en-lflow.h \
northd/inc-proc-northd.c \
northd/inc-proc-northd.h \
northd/ipam.c \
diff --git a/northd/en-lflow.c b/northd/en-lflow.c
new file mode 100644
index ..46072cb0162e
--- /dev/null
+++ b/northd/en-lflow.c
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-lflow.h"
+#include "en-northd.h"
+
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_lflow);
+
+void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+engine_set_node_state(node, EN_UPDATED);
+}
+void *en_lflow_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+return NULL;
+}
+
+void en_lflow_cleanup(void *data OVS_UNUSED)
+{
+}
diff --git a/northd/en-lflow.h b/northd/en-lflow.h
new file mode 100644
index ..0e4d522ff3fe
--- /dev/null
+++ b/northd/en-lflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_LFLOW_H
+#define EN_LFLOW_H 1
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "lib/inc-proc-eng.h"
+
+void en_lflow_run(struct engine_node *node, void *data);
+void *en_lflow_init(struct engine_node *node, struct engine_arg *arg);
+void en_lflow_cleanup(void *data);
+
+#endif /* EN_LFLOW_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 572b8de6536a..519fc1d0cb46 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -25,6 +25,7 @@
 #include "openvswitch/vlog.h"
 #include "inc-proc-northd.h"
 #include "en-northd.h"
+#include "en-lflow.h"
 #include "util.h"
 
 VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
@@ -140,6 +141,7 @@ enum sb_engine_node {
 /* Define engine nodes for other nodes. They should be defined as static to
  * avoid sparse errors. */
 static ENGINE_NODE(northd, "northd");
+static ENGINE_NODE(lflow, "lflow");
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb)
@@ -204,13 +206,14 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_add_input(_northd, _sb_load_balancer, NULL);
 engine_add_input(_northd, _sb_bfd, NULL);
 engine_add_input(_northd, _sb_fdb, NULL);
+engine_add_input(_lflow, _northd, NULL);
 
 struct engine_arg engine_arg = {
 .nb_idl = nb->idl,
 .sb_idl = sb->idl,
 };
 
-engine_init(_northd, _arg);
+engine_init(_lflow, _arg);
 }
 
 void inc_proc_northd_run(struct northd_idl_context *ctx,
diff --git a/northd/northd.c b/northd/northd.c
index 6426fcbe1215..e1097e6b301a 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -12974,7 +12974,6 @@ struct lflows_thread_pool {
 struct worker_pool *pool;
 };
 
-
 static void *
 build_lflows_thread(void *arg)
 {
@@ -14556,7 +14555,6 @@ ovnnb_db_run(struct northd_data *data,
 cleanup_stale_fdp_entries(ctx, >datapaths);
 bfd_cleanup_connections(ctx, >bfd_connections);
 stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-
 }
 
 /* Stores the list of chassis which references an ha_chassis_group.
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2 7/7] en_lflow: Generate logical flows

2021-10-18 Thread Mark Gray
Generate logical flows using 'en_flow' incremental processing node.
This node uses output data from 'en_northd' in order to generate
logical flows.

Signed-off-by: Mark Gray 
---
 northd/en-lflow.c | 12 
 northd/northd.c   |  6 +-
 northd/northd.h   |  1 +
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/northd/en-lflow.c b/northd/en-lflow.c
index 46072cb0162e..e24c00e039c3 100644
--- a/northd/en-lflow.c
+++ b/northd/en-lflow.c
@@ -23,12 +23,24 @@
 
 #include "lib/inc-proc-eng.h"
 #include "northd.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
+#include "timeval.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_lflow);
 
 void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
 {
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
+
+struct ed_type_northd *northd_data = engine_get_input_data("northd", node);
+
+stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+build_lflows(ctx, northd_data->data);
+stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+
 engine_set_node_state(node, EN_UPDATED);
 }
 void *en_lflow_init(struct engine_node *node OVS_UNUSED,
diff --git a/northd/northd.c b/northd/northd.c
index e1097e6b301a..03f321ba63df 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -13327,8 +13327,7 @@ static bool reset_parallel = false;
 
 /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database,
  * constructing their contents based on the OVN_NB database. */
-static void
-build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
 {
 struct hmap lflows;
 
@@ -14542,9 +14541,6 @@ ovnnb_db_run(struct northd_data *data,
 build_meter_groups(ctx, >meter_groups);
 build_bfd_table(ctx, >bfd_connections, >ports);
 stopwatch_stop(BUILD_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
-build_lflows(ctx, data);
-stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
 stopwatch_start(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
 ovn_update_ipv6_prefix(>ports);
 
diff --git a/northd/northd.h b/northd/northd.h
index d4bc5cf16541..07ea6899984f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -51,5 +51,6 @@ void northd_destroy(struct northd_data *data);
 void northd_init(struct northd_data *data);
 void northd_indices_create(struct northd_data *data,
struct ovsdb_idl *ovnsb_idl);
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data);
 
 #endif /* NORTHD_H */
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2 2/7] northd: Introduce incremental processing for northd

2021-10-18 Thread Mark Gray
Initial implementation adds a single node (northd). This single
node executes the northd processing pipeline but does not do so
incrementally.

In order to develop incremental processing for northd, the code
will be organised with a .c/.h file for each I-P node following
the naming convention en-.c/.h. These files will
contain definition of the node data, the main node processing
functions and change handlers (if any). The purpose of these nodes
will be coordination of the nodes work and implemention of the
relevant interfaces to plugin to the I-P framework. The actual
work that will be executed by the node will be organised into
a companion file or files. Ideally this file will follow the
naming convention of the node: e.g. en-.c is
associated with .c.

Initial node topology sees the northd node dependent on all DB
nodes. This will evolve over time.

Co-authored-by: Numan Siddique 
Signed-off-by: Numan Siddique 
Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  16 +++
 northd/automake.mk   |   4 +
 northd/en-northd.c   |  45 +++
 northd/en-northd.h   |  17 +++
 northd/inc-proc-northd.c | 254 +++
 northd/inc-proc-northd.h |  15 +++
 northd/northd.c  |  12 +-
 northd/northd.h  |   8 +-
 northd/ovn-northd.c  | 201 ---
 9 files changed, 489 insertions(+), 83 deletions(-)
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 1ccae559dff6..a3f5a7e64287 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -63,15 +63,22 @@
 #define ENGINE_MAX_INPUT 256
 #define ENGINE_MAX_OVSDB_INDEX 256
 
+#include 
+#include 
+
+#include "compiler.h"
+
 struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
+struct ovsdb_idl_txn *ovnnb_idl_txn;
 void *client_ctx;
 };
 
 /* Arguments to be passed to the engine at engine_init(). */
 struct engine_arg {
 struct ovsdb_idl *sb_idl;
+struct ovsdb_idl *nb_idl;
 struct ovsdb_idl *ovs_idl;
 };
 
@@ -347,6 +354,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_FUNC_SB(TBL_NAME) \
 ENGINE_FUNC_OVSDB(sb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN NB DB */
+#define ENGINE_FUNC_NB(TBL_NAME) \
+ENGINE_FUNC_OVSDB(nb, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -360,6 +372,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
 ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
 
+/* Macro to define an engine node which represents a table of OVN NB DB */
+#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
+ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
diff --git a/northd/automake.mk b/northd/automake.mk
index 35ad8c09d9ba..f0c1fb11c83a 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
northd/northd.c \
northd/northd.h \
northd/ovn-northd.c \
+   northd/en-northd.c \
+   northd/en-northd.h \
+   northd/inc-proc-northd.c \
+   northd/inc-proc-northd.h \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/en-northd.c b/northd/en-northd.c
new file mode 100644
index ..d310fa4dd31f
--- /dev/null
+++ b/northd/en-northd.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-northd.h"
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_northd);
+
+void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_context *ctx = eng_ctx->client_ctx;
+ovn_db_run(ctx);
+
+engine_set_node_state(node, EN_UPDATED);

[ovs-dev] [PATCH ovn v2 4/7] northd: Rename struct northd_context

2021-10-18 Thread Mark Gray
In order to prepare for a subsequent commit, rename
'struct northd_context' to 'struct northd_idl_context'. In
subsequent commits, 'struct northd_idl_context' will then be
used, only, to hold the IDL context required by northd.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c   |  2 +-
 northd/inc-proc-northd.c |  2 +-
 northd/inc-proc-northd.h |  2 +-
 northd/northd.c  | 89 
 northd/northd.h  |  4 +-
 northd/ovn-northd.c  | 10 ++---
 6 files changed, 55 insertions(+), 54 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index d310fa4dd31f..8dec51535af0 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -28,7 +28,7 @@ VLOG_DEFINE_THIS_MODULE(en_northd);
 void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
 {
 const struct engine_context *eng_ctx = engine_get_context();
-struct northd_context *ctx = eng_ctx->client_ctx;
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
 ovn_db_run(ctx);
 
 engine_set_node_state(node, EN_UPDATED);
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 85baeb07d3d9..572b8de6536a 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -213,7 +213,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_init(_northd, _arg);
 }
 
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute) {
 engine_set_force_recompute(recompute);
 engine_init_run();
diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
index 09cb8f3b3a80..6ee056dc14f5 100644
--- a/northd/inc-proc-northd.h
+++ b/northd/inc-proc-northd.h
@@ -8,7 +8,7 @@
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb);
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute);
 void inc_proc_northd_cleanup(void);
 
diff --git a/northd/northd.c b/northd/northd.c
index 9e84ee6310a9..d61368c1e406 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -1256,7 +1256,7 @@ ovn_datapath_update_external_ids(struct ovn_datapath *od)
 }
 
 static void
-join_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+join_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
struct ovs_list *sb_only, struct ovs_list *nb_only,
struct ovs_list *both, struct ovs_list *lr_list)
 {
@@ -1367,7 +1367,7 @@ is_vxlan_mode(struct ovsdb_idl *ovnsb_idl)
 }
 
 static uint32_t
-get_ovn_max_dp_key_local(struct northd_context *ctx)
+get_ovn_max_dp_key_local(struct northd_idl_context *ctx)
 {
 if (is_vxlan_mode(ctx->ovnsb_idl)) {
 /* OVN_MAX_DP_GLOBAL_NUM doesn't apply for vxlan mode. */
@@ -1377,7 +1377,7 @@ get_ovn_max_dp_key_local(struct northd_context *ctx)
 }
 
 static void
-ovn_datapath_allocate_key(struct northd_context *ctx,
+ovn_datapath_allocate_key(struct northd_idl_context *ctx,
   struct hmap *datapaths, struct hmap *dp_tnlids,
   struct ovn_datapath *od, uint32_t *hint)
 {
@@ -1397,7 +1397,7 @@ ovn_datapath_allocate_key(struct northd_context *ctx,
 }
 
 static void
-ovn_datapath_assign_requested_tnl_id(struct northd_context *ctx,
+ovn_datapath_assign_requested_tnl_id(struct northd_idl_context *ctx,
  struct hmap *dp_tnlids,
  struct ovn_datapath *od)
 {
@@ -1431,7 +1431,7 @@ ovn_datapath_assign_requested_tnl_id(struct 
northd_context *ctx,
  * Initializes 'datapaths' to contain a "struct ovn_datapath" for every logical
  * switch and router. */
 static void
-build_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+build_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
 struct ovs_list *lr_list)
 {
 struct ovs_list sb_only, nb_only, both;
@@ -2402,7 +2402,7 @@ tag_alloc_create_new_tag(struct hmap *tag_alloc_table,
 
 
 static void
-join_logical_ports(struct northd_context *ctx,
+join_logical_ports(struct northd_idl_context *ctx,
struct hmap *datapaths, struct hmap *ports,
struct hmap *chassis_qdisc_queues,
struct hmap *tag_alloc_table, struct ovs_list *sb_only,
@@ -2864,7 +2864,7 @@ sbpb_gw_chassis_needs_update(
 }
 
 static struct sbrec_ha_chassis *
-create_sb_ha_chassis(struct northd_context *ctx,
+create_sb_ha_chassis(struct northd_idl_context *ctx,
  const struct sbrec_chassis *chassis,
  const char *chassis_name, int priority)
 {
@@ -2949,7 +2949,7 @@ chassis_group_list_changed(
 }
 
 static void
-sync_ha_chassis_group_for_sbpb(struct northd_context *ctx,
+sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
 

[ovs-dev] [PATCH ovn v2 3/7] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-10-18 Thread Mark Gray
destroy_nat_entries() iterates over nat_entries using 'n_nat'
as the number of NAT entries from the NB database. This behaviour can be
incorrect as it assumes that there are 'n_nat' 'nat_entries'. 'struct
ovn_datapath' should maintain a count of 'nat_entries' in 'struct
ovn_datapath' rather than read the value from NBDB IDL to properly
account for the number of 'nat_entries'.

This issue becomes appatent when using destroy_nat_entries()
as part of an incremental processing loop:

Consider an example in which we have completed iteration x, and
started iteration x+1. If we add a NAT entry to NBDB between iteration x
and iteration x+1, od->nbr->n_nat will contain the updated value of
n_nat as the northbound record will have been updated. However, if
we do not (re)initialized the nat entries in od, od->n_nat_entries
could be equal to the previous value. This can cause destroy_nat_entries()
to loop over the wrong number of 'nat_entries' causing unexpected
behaviour.

Signed-off-by: Mark Gray 
---
 northd/northd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/northd/northd.c b/northd/northd.c
index 1321e26faa9d..9e84ee6310a9 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -603,6 +603,8 @@ struct ovn_datapath {
 
 /* NAT entries configured on the router. */
 struct ovn_nat *nat_entries;
+size_t n_nat_entries;
+
 bool has_distributed_nat;
 
 /* Set of nat external ips on the router. */
@@ -787,6 +789,7 @@ init_nat_entries(struct ovn_datapath *od)
 od->has_distributed_nat = true;
 }
 }
+od->n_nat_entries = od->nbr->n_nat;
 }
 
 static void
@@ -800,7 +803,7 @@ destroy_nat_entries(struct ovn_datapath *od)
 destroy_lport_addresses(>dnat_force_snat_addrs);
 destroy_lport_addresses(>lb_force_snat_addrs);
 
-for (size_t i = 0; i < od->nbr->n_nat; i++) {
+for (size_t i = 0; i < od->n_nat_entries; i++) {
 destroy_lport_addresses(>nat_entries[i].ext_addrs);
 }
 }
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2 1/7] inc-proc-eng: Allow definition of engine_node with global scope

2021-10-18 Thread Mark Gray
Refactor ENGINE_NODE() macro to not assign function pointers. This
allows ENGINE_NODE() to be used outside functions, creating an
engine_node with global scope (but can be statically defined within a file).
This allows more flexibility in how the I-P engine can be used as
engine nodes can be defined. Allow this is not explicitly required for
I-P it does allow for a cleaner code base as the node definitions can
be kept together outside any functions.

Additional function pointers (e.g. is_valid(), clear_tracked_data()),
may be assigned later, if required.

Signed-off-by: Mark Gray 
---
 controller/ovn-controller.c | 2 +-
 lib/inc-proc-eng.h  | 8 
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 4202f32ccaf6..48121ccce082 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -3219,7 +3219,7 @@ main(int argc, char *argv[])
 stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
 
 /* Define inc-proc-engine nodes. */
-ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones");
+ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones, "ct_zones");
 ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
 ENGINE_NODE(non_vif_data, "non_vif_data");
 ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 859b30a71c86..1ccae559dff6 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -295,19 +295,19 @@ void engine_ovsdb_node_add_index(struct engine_node *, 
const char *name,
 .init = en_##NAME##_init, \
 .run = en_##NAME##_run, \
 .cleanup = en_##NAME##_cleanup, \
-.is_valid = en_##NAME##_is_valid, \
+.is_valid = NULL, \
 .clear_tracked_data = NULL, \
 };
 
 #define ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
-#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
+#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(NAME, NAME_STR) \
 ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
-en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data;
+en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data; \
+en_##NAME.is_valid = en_##NAME##_is_valid;
 
 #define ENGINE_NODE(NAME, NAME_STR) \
-static bool (*en_##NAME##_is_valid)(struct engine_node *node) = NULL; \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
 #define ENGINE_NODE_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v2 0/7] northd: Introduce incremental processing framework

2021-10-18 Thread Mark Gray
Add the 'inc-proc-eng' framework to northd. This does *not*
add any incremental processing at this stage but provides the
framework to do so. Even in this base configuration, we see an
advantage as northd no longer processes the databases if it has
been woken only to handle, for example, a unixctl command. This
can be seen below

$ ovn-appctl -t ovn-northd stopwatch/reset
$ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show >/dev/null; done
$ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Statistics for 'ovnnb_db_run'
  Total samples: 0
  Maximum: 0 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 0.00 msec
  Long term average: 0.00 msec

Hopefully this starting point will allow others to discuss or contribute
changes to incrementally process some aspects of northd. We an also
decide if it is worth progressing with this in general.

Thanks,

v2: Rebase

Mark Gray (7):
  inc-proc-eng: Allow definition of engine_node with global scope
  northd: Introduce incremental processing for northd
  northd: Add n_nat_entries field to 'struct ovn_datapath'
  northd: Rename struct northd_context
  northd: Introduce struct northd_data
  northd: Add lflow node
  en_lflow: Generate logical flows

 controller/ovn-controller.c |   2 +-
 lib/inc-proc-eng.h  |  24 ++-
 northd/automake.mk  |   6 +
 northd/en-lflow.c   |  54 ++
 northd/en-lflow.h   |  16 ++
 northd/en-northd.c  |  65 +++
 northd/en-northd.h  |  21 ++
 northd/inc-proc-northd.c| 257 +
 northd/inc-proc-northd.h|  15 ++
 northd/northd.c | 368 +++-
 northd/northd.h |  36 +++-
 northd/ovn-northd.c | 237 +--
 12 files changed, 812 insertions(+), 289 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

-- 
2.27.0


___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn 2/3] CoPP: add self-test for bfd controller action

2021-10-15 Thread Mark Gray
On 13/10/2021 17:46, Lorenzo Bianconi wrote:
> Introduce CoPP selftest for bfd controller action
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  tests/system-ovn.at | 29 +
>  1 file changed, 29 insertions(+)
> 
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index bd425f54b..12f072b72 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -6751,6 +6751,35 @@ OVS_WAIT_UNTIL([
>  test "${n_icmp}" = "2"
>  ])
>  
> +check ovn-nbctl meter-add bfd-meter drop 1 pktps 0
> +check ovn-nbctl --wait=hv lr-copp-add R1 bfd bfd-meter
> +AT_CHECK([ovn-nbctl lr-copp-list R1 |grep bfd], [0], [dnl
> +bfd: bfd-meter
> +])
> +
> +check ovn-nbctl --bfd lr-route-add R1 240.0.0.0/8 172.16.1.50 rp-public
> +disc=$(ovn-sbctl list bfd | awk '/disc/{print $3}')
> +printf "%08x" $disc > /tmp/disc

Could you just get the value directly from the database using:

`ovn-sbctl get BFD ...`?

> +NS_EXEC([server], [tcpdump -n -i s1 udp port 3784 -Q in > bfd.pcap &])
> +ip netns exec server scapy -H <<-EOF
> +import binascii
> +f = open("/tmp/disc", "r")
> +bfd = binascii.unhexlify("20600518a899e77b" + f.readline().strip() + 
> "000f424f4240")

Please add some comments, its hard to follow what's going on.

> +p = IP(src="172.16.1.50", dst="172.16.1.1")/ UDP(dport = 3784, sport = 
> 49152) / Raw(load = bfd)
> +send (p, iface='s1', loop = 0, verbose = 0, count = 100)
> +f.close()
> +EOF
> +rm /tmp/disc
> +
> +sleep 2
> +kill $(pidof tcpdump)
> +
> +# 1pps + 1 burst size
> +OVS_WAIT_UNTIL([
> +n_tcp_rst=$(grep Final bfd.pcap | wc -l)
> +test "${n_tcp_rst}" = "2"
> +])
> +
>  kill $(pidof ovn-controller)
>  
>  as ovn-sb
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn 1/3] CoPP: add self-test for icmp{4, 6}_error controller action

2021-10-15 Thread Mark Gray
On 13/10/2021 17:46, Lorenzo Bianconi wrote:
> Introduce CoPP selftest for icmp{4,6}_error controller action
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  tests/ovn-northd.at | 23 +++
>  tests/system-ovn.at | 21 +
>  2 files changed, 44 insertions(+)
> 
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 8b9049899..3bcbdf4a9 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -3249,6 +3249,29 @@ AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
>  
>  AT_CHECK([ovn-sbctl list logical_flow | grep arp -A 2 | grep -q meter1],[1])
>  
> +check ovn-nbctl --wait=hv meter-add meter2 drop 400 pktps 10
> +check ovn-nbctl --wait=hv lr-copp-add r0 icmp4-error meter2
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +icmp4-error: meter2
> +])
> +
> +AT_CHECK([ovn-sbctl list logical_flow | grep icmp4 -A 2 | grep -q meter2])
> +
> +check ovn-nbctl --wait=hv lr-copp-del r0 icmp4-error
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +])
> +
> +check ovn-nbctl --wait=hv lr-copp-add r0 icmp6-error meter2
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +icmp6-error: meter2
> +])
> +
> +AT_CHECK([ovn-sbctl list logical_flow | grep icmp6 -A 2 | grep -q meter2])
> +
> +check ovn-nbctl --wait=hv lr-copp-del r0 icmp6-error
> +AT_CHECK([ovn-nbctl lr-copp-list r0], [0], [dnl
> +])
> +
>  check ovn-nbctl --wait=hv ls-copp-del sw1 event-elb
>  AT_CHECK([ovn-nbctl ls-copp-list sw1], [0], [dnl
>  ])
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 345384223..bd425f54b 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -6730,6 +6730,27 @@ OVS_WAIT_UNTIL([
>  test "${n_arp}" = "2"
>  ])
>  
> +check ovn-nbctl meter-add icmp-meter drop 1 pktps 0
> +check ovn-nbctl --wait=hv lr-copp-add R1 icmp4-error icmp-meter
> +AT_CHECK([ovn-nbctl lr-copp-list R1 |grep icmp4-error], [0], [dnl
> +icmp4-error: icmp-meter
> +])
> +
> +NS_EXEC([sw01], [tcpdump -n -i sw01 icmp > icmp.pcap &])
> +ip netns exec sw01 scapy -H <<-EOF
> +p = IP(src="192.168.1.2", dst="172.16.1.100", ttl=1)/ TCP(dport = 8080, 
> flags="S") / Raw(b"X"*64)

small nit: can you make the whitespace between '/'s consistent across
this statement. Only update this if you need to repost.

> +send (p, iface='sw01', loop = 0, verbose = 0, count = 100)
> +EOF
> +
> +sleep 2
> +kill $(pidof tcpdump)
> +
I feel like a sleep could inadvertently introduce a race condition on
some systems. Not sure how to avoid it though. Maybe rather than
sleeping, you could wait until "n_icmp" == 2, and then check how much
time has passed but I don't know if that would improve things

> +# 1pps + 1 burst size
> +OVS_WAIT_UNTIL([
> +n_icmp=$(grep ICMP icmp.pcap | wc -l)
> +test "${n_icmp}" = "2"
> +])
> +
>  kill $(pidof ovn-controller)
>  
>  as ovn-sb
> 

You didn't add an ICMP6 test. Maybe its not necessary?

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn-northd: Doc: Update OVN tables number

2021-10-15 Thread Mark Gray
On 11/10/2021 17:52, mh...@redhat.com wrote:
> From: Mohammad Heib 
> 
> Update old OVN tables numbers to match the correct tables number
> 
> Signed-off-by: Mohammad Heib 
> ---
>  northd/northd.c | 6 +++---
>  northd/ovn-northd.8.xml | 4 ++--
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.c
> index 32ab3baf3..0bf66e0b2 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -7440,7 +7440,7 @@ build_lswitch_lflows_admission_control(struct 
> ovn_datapath *od,
>  }
>  }
>  
> -/* Ingress table 13: ARP/ND responder, skip requests coming from localnet
> +/* Ingress table 16: ARP/ND responder, skip requests coming from localnet
>   * and vtep ports. (priority 100); see ovn-northd.8.xml for the
>   * rationale. */
>  
> @@ -7682,7 +7682,7 @@ build_lswitch_arp_nd_responder_known_ips(struct 
> ovn_port *op,
>  }
>  }
>  
> -/* Ingress table 13: ARP/ND responder, by default goto next.
> +/* Ingress table 16: ARP/ND responder, by default goto next.
>   * (priority 0)*/
>  static void
>  build_lswitch_arp_nd_responder_default(struct ovn_datapath *od,
> @@ -7693,7 +7693,7 @@ build_lswitch_arp_nd_responder_default(struct 
> ovn_datapath *od,
>  }
>  }
>  
> -/* Ingress table 13: ARP/ND responder for service monitor source ip.
> +/* Ingress table 16: ARP/ND responder for service monitor source ip.
>   * (priority 110)*/
>  static void
>  build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb,
> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> index 39f4eaa0c..d219c5618 100644
> --- a/northd/ovn-northd.8.xml
> +++ b/northd/ovn-northd.8.xml
> @@ -1870,14 +1870,14 @@ output;
>  A priority 34000 logical flow is added for each logical port which
>  has DHCPv4 options defined to allow the DHCPv4 reply packet and 
> which has
>  DHCPv6 options defined to allow the DHCPv6 reply packet from the
> -Ingress Table 16: DHCP responses.
> +Ingress Table 18: DHCP responses.
>
>  
>
>  A priority 34000 logical flow is added for each logical switch 
> datapath
>  configured with DNS records with the match udp.dst = 53
>  to allow the DNS reply packet from the
> -Ingress Table 18: DNS responses.
> +Ingress Table 20: DNS responses.
>
>  
>
> 
Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn] ipsec: Update documentation for Fedora

2021-10-14 Thread Mark Gray
When running on Fedora, it may be necessary to allow ESP and IKE traffic
through the host firewall. If not, this will result in ICMP host
unreachable messages:

13:52:10.000695 IP 192.168.122.228 > 192.168.122.125: 
ESP(spi=0xa5830a6b,seq=0x2), length 156
13:52:10.000721 IP 192.168.122.228 > 192.168.122.125: 
ESP(spi=0xa5830a6b,seq=0x2), length 156
13:52:10.000864 IP 192.168.122.125 > 192.168.122.228: ICMP host 192.168.122.125 
unreachable - admin prohibited filter, length 184
13:52:10.000874 IP 192.168.122.125 > 192.168.122.228: ICMP host 192.168.122.125 
unreachable - admin prohibited filter, length 184

This commit updates the documentation to reflect this.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2002278
Signed-off-by: Mark Gray 
---
 Documentation/tutorials/ovn-ipsec.rst | 13 +
 1 file changed, 13 insertions(+)

diff --git a/Documentation/tutorials/ovn-ipsec.rst 
b/Documentation/tutorials/ovn-ipsec.rst
index 3adef68bb697..fa35eb84b316 100644
--- a/Documentation/tutorials/ovn-ipsec.rst
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -80,6 +80,19 @@ database to false::
 
 $ ovn-nbctl set nb_global . ipsec=false
 
+.. note::
+
+   On Fedora, you may need to install firewall rules to allow ESP and IKE
+   traffic::
+
+   # systemctl start firewalld
+   # firewall-cmd --add-service ipsec
+
+   Or to make permanent::
+
+   # systemctl enable firewalld
+   # firewall-cmd --permanent --add-service ipsec
+
 Troubleshooting
 ---
 
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v2] ovn-controller: Avoid infinite replying for TCP/ICMP connection reset messages

2021-10-11 Thread Mark Gray
On 11/10/2021 10:01, mh...@redhat.com wrote:
> From: Mohammad Heib 
> 
> When the ovn controller receives an ip packet that targets a lport that has 
> ACL
> rule to reject ip packets, the controller will reply with TCP_RST or icmp4/6 
> unreachable packet
> to notify the sender that the destination is not available.
> 
> In turn, the receiver host will receive the notification packet and handle it 
> as a normal IP packet
> and if the receiver host is part of the same logical-switch/port-group or has 
> IP reject ACL rule
> it will send TCP_RST or icmp4/6 unreachable packet replying to the TCP_RST or 
> icmp4/6 unreachable
> packet we received and here we will enter to an infinity loop of replying 
> about replying which
> will consume high CPU.
> 
> To avoid such scenarios this patch proposes to drop/ignore TCP_RST or icmp4/6 
> unreachable packets
> that received on lport that has  IP reject ACL rules.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1934011
> Fixes: 64f8c9e9f ("actions: Add a new OVN action - reject {}.")
> Signed-off-by: Mohammad Heib 
> ---
>  controller/pinctrl.c | 29 +++
>  tests/ovn-northd.at  | 85 
>  2 files changed, 114 insertions(+)
> 
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index cc3edaaf4..eff599d2b 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -1934,11 +1934,40 @@ pinctrl_handle_sctp_abort(struct rconn *swconn, const 
> struct flow *ip_flow,
>  dp_packet_uninit();
>  }
>  
> +static bool
> +pinctrl_handle_reject_ignore_pkt(const struct flow *ip_flow,
> + struct dp_packet *pkt_in)
> +{
> +if (ip_flow->nw_proto == IPPROTO_TCP) {
> +struct tcp_header *th = dp_packet_l4(pkt_in);
> +if (!th || (TCP_FLAGS(th->tcp_ctl) & TCP_RST)) {
> +return true;
> +}
> +} else {
> +if (is_icmpv4(ip_flow, NULL)) {
> +struct icmp_header *ih = dp_packet_l4(pkt_in);
> +if (!ih || (ih->icmp_type == ICMP4_DST_UNREACH)) {
> +return true;
> +}
> +} else if (is_icmpv6(ip_flow, NULL)) {
> +struct icmp6_data_header *ih = dp_packet_l4(pkt_in);
> +if (!ih || (ih->icmp6_base.icmp6_type == ICMP6_DST_UNREACH)) {
> +return true;
> +}
> +}
> +}
> +return false;
> +}
> +
>  static void
>  pinctrl_handle_reject(struct rconn *swconn, const struct flow *ip_flow,
>struct dp_packet *pkt_in,
>const struct match *md, struct ofpbuf *userdata)
>  {
> +if (pinctrl_handle_reject_ignore_pkt(ip_flow, pkt_in)) {
> +return;
> +}
> +
>  if (ip_flow->nw_proto == IPPROTO_TCP) {
>  pinctrl_handle_tcp_reset(swconn, ip_flow, pkt_in, md, userdata, 
> true);
>  } else if (ip_flow->nw_proto == IPPROTO_SCTP) {
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 8b9049899..d06065a86 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -2062,6 +2062,91 @@ sw1flows3:  table=4 (ls_out_acl ), 
> priority=2003 , match=((reg0[[9]] ==
>  AT_CLEANUP
>  ])
>  
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([ACL Reject ping pong])
> +AT_KEYWORDS([ACL Reject ping pong])

:D .. nice name

Thanks for adding this. Some comments below.

> +ovn_start
> +
> +send_icmp_packet() {
> +local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 
> ip_chksum=$7 data=$8
> +shift 8
> +
> +local ip_ttl=ff
> +local ip_len=001c
> +local 
> packet=${eth_dst}${eth_src}08004500${ip_len}4000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data}
> +as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $packet
> +}
> +
> +net_add n1
> +
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
> +options:tx_pcap=hv1/vif1-tx.pcap \
> +options:rxq_pcap=hv1/vif1-rx.pcap \
> +ofport-request=1
> +
> +sim_add hv2
> +as hv2
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.2
> +ovs-vsctl -- add-port br-int hv2-vif1 -- \
> +set interface hv2-vif1 external-ids:iface-id=sw0-p2 \
> +options:tx_pcap=hv2/vif1-tx.pcap \
> +options:rxq_pcap=hv2/vif1-rx.pcap \
> +ofport-request=1
> +
> +ovn-nbctl ls-add sw0
> +
> +check ovn-nbctl lsp-add sw0 sw0-p1
> +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3"
> +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3"
> +
> +check ovn-nbctl lsp-add sw0 sw0-p2
> +check ovn-nbctl lsp-set-addresses sw0-p2 "50:54:00:00:00:04 10.0.0.4"
> +check ovn-nbctl lsp-set-port-security sw0-p2 "50:54:00:00:00:04 10.0.0.4"
> +
> +check ovn-nbctl acl-add sw0 to-lport 1002 ip reject
> +
> +OVN_POPULATE_ARP
> +
> +wait_for_ports_up
> +ovn-nbctl --wait=hv sync
> +
> +ovn-sbctl 

Re: [ovs-dev] [OVN Patch v3] northd: Optimize dp/lflow postprocessing

2021-10-11 Thread Mark Gray
On 11/10/2021 13:57, anton.iva...@cambridgegreys.com wrote:
> From: Anton Ivanov 
> 
> 1. Compute dp group hash only if there will be dp group processing.
> 2. Remove hmapx interim storage and related hmapx computation for
> single dp flows and replace it with a pre-sized hmap.
> 
> Signed-off-by: Anton Ivanov 
> ---
>  northd/northd.c | 50 -
>  1 file changed, 29 insertions(+), 21 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.c
> index e42795ca0..49948d568 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -13331,10 +13331,20 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  stopwatch_start(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
>  /* Collecting all unique datapath groups. */
>  struct hmap dp_groups = HMAP_INITIALIZER(_groups);
> -struct hmapx single_dp_lflows = HMAPX_INITIALIZER(_dp_lflows);
> -struct ovn_lflow *lflow;
> -HMAP_FOR_EACH (lflow, hmap_node, ) {
> -uint32_t hash = hash_int(hmapx_count(>od_group), 0);
> +struct hmap single_dp_lflows;
> +
> +/* Single dp_flows will never grow bigger than lflows,
> + * thus the two hmaps will remain the same size regardless
> + * of how many elements we remove from lflows and add to
> + * single_dp_lflows.
> + * Note - lflows is always sized for at least 128 flows.
> + */
> +fast_hmap_size_for(_dp_lflows, max_seen_lflow_size);
> +
> +struct ovn_lflow *lflow, *next_lflow;
> +struct hmapx_node *node;
> +HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
> +uint32_t hash;
>  struct ovn_dp_group *dpg;
>  
>  ovs_assert(hmapx_count(>od_group));
> @@ -13342,17 +13352,24 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  if (hmapx_count(>od_group) == 1) {
>  /* There is only one datapath, so it should be moved out of the
>   * group to a single 'od'. */
> -const struct hmapx_node *node;
>  HMAPX_FOR_EACH (node, >od_group) {
>  lflow->od = node->data;
>  break;
>  }
>  hmapx_clear(>od_group);
> -/* Logical flow should be re-hashed later to allow lookups. */
> -hmapx_add(_dp_lflows, lflow);
> +
> +/* Logical flow should be re-hashed to allow lookups. */
> +hash = hmap_node_hash(>hmap_node);
> +/* Remove from lflows. */
> +hmap_remove(, >hmap_node);
> +hash = 
> ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> +  hash);
> +/* Add to single_dp_lflows. */
> +hmap_insert_fast(_dp_lflows, >hmap_node, hash);
>  continue;
>  }
>  
> +hash = hash_int(hmapx_count(>od_group), 0);
>  dpg = ovn_dp_group_find(_groups, >od_group, hash);
>  if (!dpg) {
>  dpg = xzalloc(sizeof *dpg);
> @@ -13362,19 +13379,11 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  lflow->dpg = dpg;
>  }
>  
> -/* Adding datapath to the flow hash for logical flows that have only one,
> - * so they could be found by the southbound db record. */
> -const struct hmapx_node *node;
> -uint32_t hash;
> -HMAPX_FOR_EACH (node, _dp_lflows) {
> -lflow = node->data;
> -hash = hmap_node_hash(>hmap_node);
> -hmap_remove(, >hmap_node);
> -hash = ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> -  hash);
> -hmap_insert(, >hmap_node, hash);
> -}
> -hmapx_destroy(_dp_lflows);
> +/* Merge multiple and single dp hashes. */
> +
> +fast_hmap_merge(, _dp_lflows);
> +
> +hmap_destroy(_dp_lflows);
>  
>  /* Push changes to the Logical_Flow table to database. */
>  const struct sbrec_logical_flow *sbflow, *next_sbflow;
> @@ -13507,7 +13516,6 @@ build_lflows(struct northd_context *ctx, struct hmap 
> *datapaths,
>  }
>  
>  stopwatch_stop(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
> -struct ovn_lflow *next_lflow;
>  HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
>  const char *pipeline = ovn_stage_get_pipeline_name(lflow->stage);
>  uint8_t table = ovn_stage_get_table(lflow->stage);
> 
Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] sbctl: add the capability to configure static mac_bindings entries

2021-10-11 Thread Mark Gray
On 28/09/2021 19:28, Lorenzo Bianconi wrote:
> Introduce the two following commands to configure and dump static
> L2 address bindings:
> 
> $ovn-sbctl set-mac-binding 192.168.1.100 00:11:22:33:44:55 vif0
> $ovn-sbctl list-mac-binding
> [ 192.168.1.100 00:11:22:33:44:55 S ]

Is there any reason why this is an `ovn-sbctl` command rather than an
`ovn-nbctl` command?

As the CMS should only really be interacting with OVN via the NBDB, I
think this should be configured via ovn-nbctl and should form part of
the northbound database somewhere.

> 
> https://bugzilla.redhat.com/show_bug.cgi?id=1845111
> Signed-off-by: Lorenzo Bianconi 
> ---
>  controller/pinctrl.c  |  3 +-
>  ovn-sb.ovsschema  |  7 +++--
>  ovn-sb.xml|  3 ++
>  tests/ovn-sbctl.at| 39 +
>  utilities/ovn-sbctl.c | 68 +++
>  5 files changed, 116 insertions(+), 4 deletions(-)
> 
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index cc3edaaf4..c56e800cf 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -4135,7 +4135,8 @@ mac_binding_add_to_sb(struct ovsdb_idl_txn 
> *ovnsb_idl_txn,
>  sbrec_mac_binding_set_ip(b, ip);
>  sbrec_mac_binding_set_mac(b, mac_string);
>  sbrec_mac_binding_set_datapath(b, dp);
> -} else if (strcmp(b->mac, mac_string)) {
> +sbrec_mac_binding_set_static_(b, false);
> +} else if (strcmp(b->mac, mac_string) && !b->static_) {
>  sbrec_mac_binding_set_mac(b, mac_string);
>  }
>  }
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index e5ab41db9..0eb9df19c 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>  "name": "OVN_Southbound",
> -"version": "20.20.0",
> -"cksum": "605270161 26670",
> +"version": "20.21.0",
> +"cksum": "4055366137 26717",
>  "tables": {
>  "SB_Global": {
>  "columns": {
> @@ -241,7 +241,8 @@
>  "ip": {"type": "string"},
>  "mac": {"type": "string"},
>  "datapath": {"type": {"key": {"type": "uuid",
> -  "refTable": 
> "Datapath_Binding",
> +  "refTable": 
> "Datapath_Binding"}}},
> +"static": {"type": "boolean"}},
>  "indexes": [["logical_port", "ip"]],
>  "isRoot": true},
>  "DHCP_Options": {
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 2d4d47d10..e6c74a328 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -3378,6 +3378,9 @@ tcp.flags = RST;
>  
>The logical datapath to which the logical port belongs.
>  
> +
> +  The entry has been manually created by the CMS and not discovered by 
> OVN.
> +
>
>  
>
> diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at
> index 1d1eee23e..ea343ff84 100644
> --- a/tests/ovn-sbctl.at
> +++ b/tests/ovn-sbctl.at
> @@ -243,3 +243,42 @@ Total number of logical flows = 0
>  ])
>  ])
>  
> +dnl -
> +
> +OVN_SBCTL_TEST([ovn_sbctl_mac_bindings], [ovn-sbctl - mac-bindings], [
> +AT_CHECK([ovn-nbctl ls-add sw0])
> +AT_CHECK([ovn-nbctl lsp-add sw0 vif0])
> +AT_CHECK([ovn-nbctl lsp-set-addresses vif0 "f0:ab:cd:ef:01:02 192.168.1.2"])
> +AT_CHECK([ovn-nbctl --wait=sb sync])
> +
> +AT_CHECK([ovn-sbctl set-mac-binding 192.168.1.100 00:11:22:33:44:55 vif0])
> +AT_CHECK([ovn-sbctl list-mac-binding], [0], [dnl
> +[[ 192.168.1.100 00:11:22:33:44:55 S ]]
> +])
> +
> +AT_CHECK([ovn-sbctl set-mac-binding 192.168.1.101 00:11:22:33:44:66 vif0])
> +AT_CHECK([ovn-sbctl list-mac-binding |sort], [0], [dnl
> +[[ 192.168.1.100 00:11:22:33:44:55 S ]]
> +[[ 192.168.1.101 00:11:22:33:44:66 S ]]
> +])
> +
> +# sanity checks
> +AT_CHECK([ovn-sbctl set-mac-binding 192.168.1.101 00:11:22:33:44:66 vif1])
> +AT_CHECK([ovn-sbctl list-mac-binding |sort], [0], [dnl
> +[[ 192.168.1.100 00:11:22:33:44:55 S ]]
> +[[ 192.168.1.101 00:11:22:33:44:66 S ]]
> +])
> +
> +AT_CHECK([ovn-sbctl set-mac-binding 192.168.1.101.2 00:11:22:33:44:66 vif0])
> +AT_CHECK([ovn-sbctl list-mac-binding |sort], [0], [dnl
> +[[ 192.168.1.100 00:11:22:33:44:55 S ]]
> +[[ 192.168.1.101 00:11:22:33:44:66 S ]]
> +])
> +
> +AT_CHECK([ovn-sbctl set-mac-binding 192.168.1.102 00:11:22:33:44:66:77 vif0])
> +AT_CHECK([ovn-sbctl list-mac-binding |sort], [0], [dnl
> +[[ 192.168.1.100 00:11:22:33:44:55 S ]]
> +[[ 192.168.1.101 00:11:22:33:44:66 S ]]
> +])
> +])
> +
> diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
> index 4d7e7d670..6d581887b 100644
> --- a/utilities/ovn-sbctl.c
> +++ b/utilities/ovn-sbctl.c
> @@ -333,6 +333,7 @@ pre_get_info(struct ctl_context *ctx)
>  ovsdb_idl_add_column(ctx->idl, _mac_binding_col_logical_port);
>  ovsdb_idl_add_column(ctx->idl, _mac_binding_col_ip);
>  ovsdb_idl_add_column(ctx->idl, _mac_binding_col_mac);
> +ovsdb_idl_add_column(ctx->idl, 

Re: [ovs-dev] [OVN Patch v2] northd: Optimize dp/lflow postprocessing

2021-10-11 Thread Mark Gray
On 08/10/2021 17:03, anton.iva...@cambridgegreys.com wrote:
> From: Anton Ivanov 
> 
> 1. Compute dp group hash only if there will be dp group processing.
> 2. Remove hmapx interim storage and related hmapx computation for
> single dp flows and replace it with a pre-sized hmap.
> 
> Signed-off-by: Anton Ivanov 
> ---

I tested the performance of this using the following on a large database:

`ovn-appctl -t ovn-northd stopwatch/reset; ovn-appctl -t ovn-northd
stopwatch/show lflows_dp_groups `

With patch:
Run 1: 1572ms
Run 2: 1536ms
Run 3: 1562ms

Without patch:
Run 1: 1640ms
Run 2: 1622ms
Run 3: 1646ms

So looks like there is a ~5% improvement there.

It passed UTs and system tests.

One small comment below otherwise
Acked-by: Mark D. Gray 


>  northd/northd.c | 48 
>  ovs |  2 +-
>  2 files changed, 29 insertions(+), 21 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.> index e42795ca0..a3c3dbcf9 
> 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -13331,10 +13331,20 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  stopwatch_start(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
>  /* Collecting all unique datapath groups. */
>  struct hmap dp_groups = HMAP_INITIALIZER(_groups);
> -struct hmapx single_dp_lflows = HMAPX_INITIALIZER(_dp_lflows);
> -struct ovn_lflow *lflow;
> -HMAP_FOR_EACH (lflow, hmap_node, ) {
> -uint32_t hash = hash_int(hmapx_count(>od_group), 0);
> +struct hmap single_dp_lflows;
> +
> +/* Single dp_flows will never grow bigger than lflows,
> + * thus the two hmaps will remain the same size regardless
> + * of how many elements we remove from lflows and add to
> + * single_dp_lflows.
> + * Note - lflows is always sized for at least 128 flows.
> + */
> +fast_hmap_size_for(_dp_lflows, max_seen_lflow_size);
> +
> +struct ovn_lflow *lflow, *next_lflow;
> +struct hmapx_node *node;
> +HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
> +uint32_t hash;
>  struct ovn_dp_group *dpg;
>  
>  ovs_assert(hmapx_count(>od_group));
> @@ -13342,17 +13352,24 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  if (hmapx_count(>od_group) == 1) {
>  /* There is only one datapath, so it should be moved out of the
>   * group to a single 'od'. */
> -const struct hmapx_node *node;
>  HMAPX_FOR_EACH (node, >od_group) {
>  lflow->od = node->data;
>  break;
>  }
>  hmapx_clear(>od_group);
> +
>  /* Logical flow should be re-hashed later to allow lookups. */

This comment should be changed. Maybe just remove "later"

> -hmapx_add(_dp_lflows, lflow);
> +hash = hmap_node_hash(>hmap_node);
> +/* Remove from lflows. */
> +hmap_remove(, >hmap_node);
> +hash = 
> ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> +  hash);
> +/* Add to single_dp_lflows. */
> +hmap_insert_fast(_dp_lflows, >hmap_node, hash);
>  continue;
>  }
>  
> +hash = hash_int(hmapx_count(>od_group), 0);
>  dpg = ovn_dp_group_find(_groups, >od_group, hash);
>  if (!dpg) {
>  dpg = xzalloc(sizeof *dpg);
> @@ -13362,19 +13379,11 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  lflow->dpg = dpg;
>  }
>  
> -/* Adding datapath to the flow hash for logical flows that have only one,
> - * so they could be found by the southbound db record. */
> -const struct hmapx_node *node;
> -uint32_t hash;
> -HMAPX_FOR_EACH (node, _dp_lflows) {
> -lflow = node->data;
> -hash = hmap_node_hash(>hmap_node);
> -hmap_remove(, >hmap_node);
> -hash = ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> -  hash);
> -hmap_insert(, >hmap_node, hash);
> -}
> -hmapx_destroy(_dp_lflows);
> +/* Merge multiple and single dp hashes. */
> +
> +fast_hmap_merge(, _dp_lflows);
> +
> +hmap_destroy(_dp_lflows);
>  
>  /* Push changes to the Logical_Flow table to database. */
>  const struct sbrec_logical_flow *sbflow, *next_sbflow;
> @@ -13507,7 +13516,6 @@ build_lflows(struct northd_context *ctx, struct hmap 
> *datapaths,
>  }
>  
>  stopwatch_stop(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
> -struct ovn_lflow *next_lflow;
>  HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
>  const char *pipeline = ovn_stage_get_pipeline_name(lflow->stage);
>  uint8_t table = ovn_stage_get_table(lflow->stage);
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [OVN Patch] northd: Optimize dp/lflow postprocessing

2021-10-08 Thread Mark Gray
On 15/09/2021 17:21, anton.iva...@cambridgegreys.com wrote:
> From: Anton Ivanov 
> 
> 1. Compute dp group hash only if there will be dp group processing.
> 2. Remove hmapx interim storage and related hmapx computation for
> single dp flows and replace it with a pre-sized hmap.

Hi Anton,

This needs a rebase. If you do it and cc me, I can review.

Mark

> 
> Signed-off-by: Anton Ivanov 
> ---
>  northd/ovn-northd.c | 55 -
>  ovs |  2 +-
>  2 files changed, 36 insertions(+), 21 deletions(-)
> 
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index baaddb73e..9edd1e0e4 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -13178,6 +13178,11 @@ build_lflows(struct northd_context *ctx, struct hmap 
> *datapaths,
>  igmp_groups, meter_groups, lbs,
>  bfd_connections);
>  
> +/* Parallel build may result in a suboptimal hash. Resize the
> + * hash to a correct size before doing lookups */
> +
> +hmap_expand();
> +
>  if (hmap_count() > max_seen_lflow_size) {
>  max_seen_lflow_size = hmap_count();
>  }
> @@ -13185,10 +13190,22 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  stopwatch_start(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
>  /* Collecting all unique datapath groups. */
>  struct hmap dp_groups = HMAP_INITIALIZER(_groups);
> -struct hmapx single_dp_lflows = HMAPX_INITIALIZER(_dp_lflows);
> -struct ovn_lflow *lflow;
> -HMAP_FOR_EACH (lflow, hmap_node, ) {
> -uint32_t hash = hash_int(hmapx_count(>od_group), 0);
> +struct hmap single_dp_lflows;
> +
> +/* Single dp_flows will never grow bigger than lflows,
> + * thus the two hmaps will remain the same size regardless
> + * of how many elements we remove from lflows and add to
> + * single_dp_lflows.
> + * Note - lflows is always sized for max_seen_lflow_size.
> + * If this iteration has resulted in a smaller lflow count,
> + * the correct sizing is from the previous ones.
> + */
> +fast_hmap_size_for(_dp_lflows, max_seen_lflow_size);
> +
> +struct ovn_lflow *lflow, *next_lflow;
> +struct hmapx_node *node;
> +HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
> +uint32_t hash;
>  struct ovn_dp_group *dpg;
>  
>  ovs_assert(hmapx_count(>od_group));
> @@ -13196,17 +13213,24 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  if (hmapx_count(>od_group) == 1) {
>  /* There is only one datapath, so it should be moved out of the
>   * group to a single 'od'. */
> -const struct hmapx_node *node;
>  HMAPX_FOR_EACH (node, >od_group) {
>  lflow->od = node->data;
>  break;
>  }
>  hmapx_clear(>od_group);
> +
>  /* Logical flow should be re-hashed later to allow lookups. */
> -hmapx_add(_dp_lflows, lflow);
> +hash = hmap_node_hash(>hmap_node);
> +/* Remove from lflows. */
> +hmap_remove(, >hmap_node);
> +hash = 
> ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> +  hash);
> +/* Add to single_dp_lflows. */
> +hmap_insert_fast(_dp_lflows, >hmap_node, hash);
>  continue;
>  }
>  
> +hash = hash_int(hmapx_count(>od_group), 0);
>  dpg = ovn_dp_group_find(_groups, >od_group, hash);
>  if (!dpg) {
>  dpg = xzalloc(sizeof *dpg);
> @@ -13216,19 +13240,11 @@ build_lflows(struct northd_context *ctx, struct 
> hmap *datapaths,
>  lflow->dpg = dpg;
>  }
>  
> -/* Adding datapath to the flow hash for logical flows that have only one,
> - * so they could be found by the southbound db record. */
> -const struct hmapx_node *node;
> -uint32_t hash;
> -HMAPX_FOR_EACH (node, _dp_lflows) {
> -lflow = node->data;
> -hash = hmap_node_hash(>hmap_node);
> -hmap_remove(, >hmap_node);
> -hash = ovn_logical_flow_hash_datapath(>od->sb->header_.uuid,
> -  hash);
> -hmap_insert(, >hmap_node, hash);
> -}
> -hmapx_destroy(_dp_lflows);
> +/* Merge multiple and single dp hashes. */
> +
> +fast_hmap_merge(, _dp_lflows);
> +
> +hmap_destroy(_dp_lflows);
>  
>  /* Push changes to the Logical_Flow table to database. */
>  const struct sbrec_logical_flow *sbflow, *next_sbflow;
> @@ -13361,7 +13377,6 @@ build_lflows(struct northd_context *ctx, struct hmap 
> *datapaths,
>  }
>  
>  stopwatch_stop(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec());
> -struct ovn_lflow *next_lflow;
>  HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, ) {
>  const char *pipeline = 

Re: [ovs-dev] [PATCH ovn] tests: fix flaky "ovn-ic -- gateway sync" test

2021-10-08 Thread Mark Gray
On 07/10/2021 19:04, Vladislav Odintsov wrote:
> Sometimes when ovn daemons in test sandbox were running slower than
> usual (more often in ASAN tests), test 'ovn-ic -- gateway sync'
> failed if chassis was not created yet.
> 
> This patch fixes such situation by adding await for chassis to
> appear.
> 
> Test fail example:
> 
> # ../../../tests/ovn-ic.at:119: ovn_as az2 ovn-sbctl show | sort -r
> # --- -   2021-10-07 12:50:45.178529089 +
> # +++ 
> /home/runner/work/ovn/ovn/ovn-21.09.90/_build/sub/tests/testsuite.dir/at-groups/1069/stdout
>  2021-10-07 12:50:45.169509348 +
> # @@ -1,9 +1 @@
> # -Chassis gw1
> # -hostname: gw1
> # -Encap vxlan
> # -Encap geneve
> # -options: {csum="true"}
> # -options: {csum="true"}
> # -ip: "192.168.0.1"
> # -ip: "192.168.0.1"
> 
> 1069. ovn-ic.at:119: 1069. ovn-ic -- gateway sync -- ovn-northd -- 
> dp-groups=no (ovn-ic.at:119): FAILED (ovn-ic.at:119)
> 
> Signed-off-by: Vladislav Odintsov 
> ---
>  tests/ovn-ic.at | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> index 15560334d..3faa9629a 100644
> --- a/tests/ovn-ic.at
> +++ b/tests/ovn-ic.at
> @@ -129,6 +129,7 @@ ovs-vsctl add-br br-phys
>  ovn_az_attach az1 n1 br-phys 192.168.0.1
>  ovs-vsctl set open . external-ids:ovn-is-interconn=true 
> external-ids:hostname=gw1
>  
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-sbctl show | grep "192.168.0.1"])
>  AT_CHECK([ovn_as az2 ovn-sbctl show | sort -r], [0], [dnl
>  Chassis gw1
>  hostname: gw1
> 

Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn-controller: Avoid infinite replying for TCP/ICMP connection reset messages

2021-10-07 Thread Mark Gray
On 06/10/2021 16:28, mh...@redhat.com wrote:
> From: Mohammad Heib 
> 
> When the ovn controller receives an ip packet that targets a lport that has 
> ACL
> rule to reject ip packets, the controller will reply with TCP_RST or icmp4/6 
> unreachable packet
> to notify the sender that the destination is not available.
> 
> In turn, the receiver host will receive the notification packet and handle it 
> as a normal IP packet
> and if the receiver host is part of the same logical-switch/port-group or has 
> IP reject ACL rule
> it will send TCP_RST or icmp4/6 unreachable packet replying to the TCP_RST or 
> icmp4/6 unreachable
> packet we received and here we will enter to an infinity loop of replying 
> about replying which
> will consume high CPU.
> 
> To avoid such scenarios this patch proposes to drop/ignore TCP_RST or icmp4/6 
> unreachable packets
> that received on lport that has  IP reject ACL rules.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1934011
> Fixes: 64f8c9e9f ("actions: Add a new OVN action - reject {}.")
> Signed-off-by: Mohammad Heib 

Looks good. Could you add a test?

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] northd: Change the default value of ignore_lsp_down to true.

2021-10-04 Thread Mark Gray
On 02/10/2021 08:11, Han Zhou wrote:
> The current default behavior is that ARP responder flows for VIFs are
> added by northd after the port-binding state is UP, which creates more
> trouble than benefit in most use cases. To make the default behavior
> desirable for majority of the use cases, set the option ignore_lsp_down
> to true by default. This would help saving the control plane cost in
> large scale environment, reduce the e2e latency for all flows to be
> installed for a VIF, and making the VIF readiness checking more convenient
> in test cases and likely in CMS as well. User can still set it to false
> in circumstances (if any) when this behavior is not desired.
> 
> Signed-off-by: Han Zhou 

Thanks Han. This seems to be good to me but I think someone else who is
more familiar with some of the original problems should give it a look
over in case I am missing something.

Acked-by: Mark D. Gray 

> ---
>  NEWS | 4 
>  northd/northd.c  | 2 +-
>  northd/ovn_northd.dl | 2 +-
>  ovn-nb.xml   | 2 +-
>  tests/ovn-northd.at  | 3 ++-
>  5 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index 8a21c029e..348f3f548 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -12,6 +12,10 @@ OVN v21.09.0 - xx xxx 
>- Allow static routes without nexthops.
>- Enabled logical dp groups as a default.  CMS should disable it if not
>  desired.
> +  - Set ignore_lsp_down to true as default, so that ARP responder flows are
> +installed together with other flows when a logical switch port is 
> created,
> +without having to wait for the port to be UP.  CMS should set it to false
> +if not desired.
>  
>  OVN v21.06.0 - 18 Jun 2021
>  -
> diff --git a/northd/northd.c b/northd/northd.c
> index cf2467fe1..5ffd6b8eb 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -14304,7 +14304,7 @@ ovnnb_db_run(struct northd_context *ctx,
>  controller_event_en = smap_get_bool(>options,
>  "controller_event", false);
>  check_lsp_is_up = !smap_get_bool(>options,
> - "ignore_lsp_down", false);
> + "ignore_lsp_down", true);
>  
>  build_datapaths(ctx, datapaths, lr_list);
>  build_ovn_lbs(ctx, datapaths, );
> diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
> index 22913f05a..7154fed13 100644
> --- a/northd/ovn_northd.dl
> +++ b/northd/ovn_northd.dl
> @@ -753,7 +753,7 @@ Northd_Probe_Interval[interval] :-
>  relation CheckLspIsUp[bool]
>  CheckLspIsUp[check_lsp_is_up] :-
>  nb in nb::NB_Global(),
> -var check_lsp_is_up = not nb.options.get_bool_def(i"ignore_lsp_down", 
> false).
> +var check_lsp_is_up = not nb.options.get_bool_def(i"ignore_lsp_down", 
> true).
>  CheckLspIsUp[true] :-
>  Unit(),
>  not nb in nb::NB_Global().
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 390cc5a44..d8266ed4d 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -236,7 +236,7 @@
>resolved even before the relevant VM/container is running. For
>environments where this is not an issue, setting it to
>true can reduce the load and latency of the control
> -  plane. The default value is false.
> +  plane. The default value is true.
>  
>
>  
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index c5400d806..3eebb55b6 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -1918,6 +1918,7 @@ OVN_FOR_EACH_NORTHD([
>  AT_SETUP([ignore_lsp_down])
>  ovn_start
>  
> +ovn-nbctl set NB_Global . options:ignore_lsp_down=false
>  ovn-nbctl ls-add sw0
>  ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 "aa:aa:aa:aa:aa:aa 
> 10.0.0.1"
>  
> @@ -4922,7 +4923,7 @@ check ovn-nbctl lsp-add sw0 lsp0 \
>  
>  check ovn-nbctl --wait=sb sync
>  AT_CHECK([ovn-sbctl --columns=tags list logical_flow | grep lsp0 -c], [0], 
> [dnl
> -9
> +10
>  ])
>  
>  AT_CLEANUP
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn.at: Fix flaky tests "VLAN transparency, passthru=true, multiple hosts"

2021-10-01 Thread Mark Gray
On 01/10/2021 14:26, Xavier Simonart wrote:
> Tests were waiting for ports to be reported up before sending packets.
> However, waiting for both ports to be up is not enough to guarantee
> that all flows are installed for both ports.
> We now wait for last flows (implementing switching to localnet port)
> are installed.
> Following tests were are fixed:
> - VLAN transparency, passthru=true, multiple hosts
> - VLAN transparency, passthru=true, multiple hosts, custom ethtype
> - VLAN transparency, passthru=true, multiple hosts, flat/untagged
> 
> Signed-off-by: Xavier Simonart 
> ---
Looks good other than the comment I have in:
(ovn.at: Fix flaky test "controller I-P handling with monitoring disabled")

https://mail.openvswitch.org/pipermail/ovs-dev/2021-October/388223.html

>  tests/ovn.at | 21 -
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/ovn.at b/tests/ovn.at
> index fc8f31d06..cc940701f 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -3413,6 +3413,14 @@ for i in 1 2; do
>options:rxq_pcap=vif$i-rx.pcap \
>ofport-request=$i
>  OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp$i` = xup])
> +# Waiting for both ports to be up is not enough to guarantee that all 
> flows are installed.
> +# Wait for flows implementing switching to localnet port.
> +OVS_WAIT_UNTIL([
> +test $(as hv-$i ovs-ofctl dump-flows br-int | \
> +grep "table=38" | \
> +grep "resubmit(,38)" -c) -eq 1
> +])
> +
>  done
>  
>  test_packet() {
> @@ -3478,8 +3486,13 @@ for i in 1 2; do
>options:rxq_pcap=vif$i-rx.pcap \
>ofport-request=$i
>  wait_for_ports_up lsp$i
> -done
> +OVS_WAIT_UNTIL([
> +test $(ovs-ofctl dump-flows br-int | \
> +grep "table=38" | \
> +grep "resubmit(,38)" -c) -eq 1
> +])
>  
> +done
>  # create taps on fabric to check vlan encapsulation there
>  for i in 1 2; do
>  as hv-$i
> @@ -3561,6 +3574,12 @@ for i in 1 2; do
>options:rxq_pcap=vif$i-rx.pcap \
>ofport-request=$i
>  OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp$i` = xup])
> +OVS_WAIT_UNTIL([
> +test $(ovs-ofctl dump-flows br-int | \
> +grep "table=38" | \
> +grep "resubmit(,38)" -c) -eq 1
> +])
> +
>  done
>  
>  for i in 1 2; do
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn.at: Fix flaky test "controller I-P handling with monitoring disabled".

2021-10-01 Thread Mark Gray
On 27/09/2021 12:13, Xavier Simonart wrote:
> Hi Mark

Sorry for the late reply. If you cc me, I will usually reply earlier.

> 
> After further investigation, checking that port is up does not fix the
> issue, as port up is reported too early by the ovn controller (before all
> flows are installed), when using conditional monitoring.
> 
> I proposed different potential solutions on the mailing list and consensus
> seems to be to leave OVN as is (i.e. port is still reported up too early)
> and only fix the test cases. Fully fixing the port up issue is perceived as
> too risky for the benefit.
> 
> For this test case, there is one additional issue: when port is reported up
> (both conditional monitoring and monitor-all), ovn-controller adds some
> more flows related for ARP handling. Hence, counting the number of flows
> when port is up might/might not take into account those flows and the test
> might fail from time to time...
> As a consequence, I propose to modify the patch in the following way: still
> use an OVS_WAIT_UNTIL, but check whether ARP responder has been installed
> by counting the number of flows related to it.

What would happen if a developer changed how the ARP responder flows
were generated (e.g. the number of them, or whether or not they were
installed at all)? Would this cause this test to fail consistently so it
could be caught?

> 
> Thanks
> Xavier
> 
> On Thu, Sep 16, 2021 at 1:23 PM Xavier Simonart  wrote:
> 
>> Hi Mark
>>
>> Thanks for looking into this.
>> Yes and no... I do not think that the patch itself will help, but it
>> pointed me to the existence of Logical_Switch_Port.up, which in this case
>> should do the trick.
>>
>> I will update the patch: instead of looking at the flows, I will use
>> something like
>>  *wait_column "true" nb:Logical_Switch_Port up name=sw0-p1*
>>
>> Thanks
>> Xavier
>>
>> On Thu, Sep 16, 2021 at 11:40 AM Mark Gray  wrote:
>>
>>> On 15/09/2021 09:52, Xavier Simonart wrote:
>>>> Test was waiting for port to be up in SBDB before checking number of
>>> flows
>>>
>>> Would this feature prevent this?
>>>
>>> 5c3371922994 ("if-status: Add OVS interface status management module.")
>>>
>>>> in OVS. However, there is no guarantee that all flows are installed
>>>> in OVS when port is up. Test was randomly failing as some flows were
>>>> installed, but not all.
>>>> To fix this, we wait until the last flow (with actions=output) is
>>>> installed.
>>>> Also fixed small typo in logging (for the same test).
>>>>
>>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2004390
>>>> Fixes: f8a81693b0 ("ovn-controller: Fix the missing flows with
>>> monitor-all set to True")
>>>> Signed-off-by: Xavier Simonart 
>>>> ---
>>>>  tests/ovn.at | 28 ++--
>>>>  1 file changed, 26 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/tests/ovn.at b/tests/ovn.at
>>>> index 30625ec37..18aeacd02 100644
>>>> --- a/tests/ovn.at
>>>> +++ b/tests/ovn.at
>>>> @@ -23448,6 +23448,12 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>
>>>>  wait_for_ports_up sw0-p1
>>>>
>>>> +# Wait for last flow to be installed
>>>> +OVS_WAIT_UNTIL([
>>>> +test $(as hv1 ovs-ofctl dump-flows br-int | \
>>>> +grep "actions=output" -c) -eq 1
>>>> +])
>>>> +
>>>>  # Get the number of OF flows in hv1 and hv2
>>>>  hv1_offlows=$(as hv1 ovs-ofctl dump-flows br-int | wc -l)
>>>>  echo "hv1 flows : $hv1_offlows"
>>>> @@ -23462,6 +23468,12 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>
>>>>  wait_for_ports_up sw0-p2
>>>>
>>>> +# Wait for last flow to be installed
>>>> +OVS_WAIT_UNTIL([
>>>> +test $(as hv2 ovs-ofctl dump-flows br-int | \
>>>> +grep "actions=output" -c) -eq 1
>>>> +])
>>>> +
>>>>  hv2_offlows=$(as hv2 ovs-ofctl dump-flows br-int | wc -l)
>>>>  echo "hv2 flows : $hv2_offlows"
>>>>  AT_CHECK([test $hv2_offlows -gt 0])
>>>> @@ -23500,9 +23512,15 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>
>>>>  wait_for_ports_up sw0-p1
>>>>
>>>> +# Wait for last flow to be installed
>>>> +OVS_WAIT_UNTIL([
>>>> +test $(as 

Re: [ovs-dev] [PATCH ovn v4 7/7] northd: Add functionality to runtime node

2021-09-29 Thread Mark Gray
On 16/09/2021 08:08, Han Zhou wrote:
> On Fri, Sep 3, 2021 at 5:22 AM Mark Gray  wrote:
>>
>> Update the runtime node to initialize and destroy some common data
>> used by multiple functions in northd.
> 
> Hi Mark,
> 
> It looks good overall as an initiate step to employ the inc-proc engine for
> ovn-northd. It is great that it achieves the no-input-change-no-compute
> outcome with this series.
> However, for the en-runtime node it doesn't look right. I understand it is
> only for demonstration purposes and is supposed to evolve, but it may look
> misleading in how would we expand it further for I-P:
> 
> 1) I think the I-P engine should focus on data dependency. Each node should
> define its data (output data computed by the node's run()/change-handlers).
> The en-runtime node defines its own data as lr_list, datapaths and ports,
> but the run() function merely initiates empty data structures that are
> later filled by en-northd, which is wrong. Instead, en-runtime should have
> its own data computed according to its input (all those NB/SB  tables), and
> then en-northd should use en-runtime data  in a read-only fashion. It is
> better not adding this node if we don't have this data dependency defined.
> 
> 2) en-northd run() calls ovn_db_run(), which accesses the inputs (DB
> tables) using the northd_context instead of the data from its input nodes.
> If we really want to use the engine for incremental processing, then I
> think the first step is to make sure we never access data through any
> global context in engine functions, and only use input data from the engine
> nodes it depends on. The engine context should only contain idl_txn for
> writing to DBs (even this could be improved so that we don't have any
> global ctx in engines at all, but at least that's how we are living with in
> ovn-controller). Otherwise it would be hard to ensure correctness of I-P.
> For example, what if in ovn_db_run() it depends on some data from the
> context that is not in any of the input nodes, and now if that data
> changes, the ovn_db_run() won't be triggered any more because engine inputs
> not changed, and this would be a bug.

Thanks for this feedback. I have posted a new series. I split it
differently into two nodes - en_northd, and en_flow. en_northd does
everything but generates the lflows and, crucially (as you pointed out),
only depends on the output data from en_northd.
> 
> Thanks,
> Han
> 
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  northd/en-northd.c  |  9 -
>>  northd/en-runtime.c | 30 --
>>  northd/en-runtime.h |  8 
>>  northd/northd.c | 15 +--
>>  northd/northd.h |  5 -
>>  5 files changed, 53 insertions(+), 14 deletions(-)
>>
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> index d310fa4dd31f..2a3250f3d57a 100644
>> --- a/northd/en-northd.c
>> +++ b/northd/en-northd.c
>> @@ -19,6 +19,7 @@
>>  #include 
>>
>>  #include "en-northd.h"
>> +#include "en-runtime.h"
>>  #include "lib/inc-proc-eng.h"
>>  #include "northd.h"
>>  #include "openvswitch/vlog.h"
>> @@ -29,7 +30,13 @@ void en_northd_run(struct engine_node *node, void
> *data OVS_UNUSED)
>>  {
>>  const struct engine_context *eng_ctx = engine_get_context();
>>  struct northd_context *ctx = eng_ctx->client_ctx;
>> -ovn_db_run(ctx);
>> +
>> +struct ed_type_runtime *runtime_data =
>> + engine_get_input_data("runtime", node);
>> +
>> +ovn_db_run(ctx, _data->lr_list,
>> +_data->datapaths,
>> +_data->ports);
>>
>>  engine_set_node_state(node, EN_UPDATED);
>>
>> diff --git a/northd/en-runtime.c b/northd/en-runtime.c
>> index aac01cd0351f..b8e5766823bf 100644
>> --- a/northd/en-runtime.c
>> +++ b/northd/en-runtime.c
>> @@ -19,7 +19,9 @@
>>  #include 
>>
>>  #include "en-runtime.h"
>> +#include "openvswitch/hmap.h"
>>  #include "lib/inc-proc-eng.h"
>> +#include "openvswitch/list.h"
>>  #include "northd.h"
>>  #include "openvswitch/vlog.h"
>>
>> @@ -27,14 +29,38 @@ VLOG_DEFINE_THIS_MODULE(en_runtime);
>>
>>  void en_runtime_run(struct engine_node *node, void *data OVS_UNUSED)
>>  {
>> +struct ed_type_runtime *runtime_data = data;
>> +
>> +struct ovs_list *lr_list = _data->lr_list;
>> +struct hmap *datapaths = _data->datapaths;
>> +struct hmap *ports = _da

Re: [ovs-dev] [PATCH ovn v4 5/7] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-09-29 Thread Mark Gray
On 15/09/2021 18:58, Mark Michelson wrote:
> On 9/14/21 1:27 PM, Mark Gray wrote:
>> On 13/09/2021 21:41, Mark Michelson wrote:
>>> Hi Mark,
>>>
>>> Of all the patches in this series, this is the one I am least sure about.
>> Thanks for looking over these.
>>
>>>
>>> It seems simple enough, but it's not clear to me
>>>
>>> 1) Why would the number of nat entries on an ovn_datapath differ from
>>> what's in the database? Since this series doesn't introduce any "real"
>>> incremental processing, we should be recreating the ovn_datapath on
>>> every iteration. And on each iteration, we should have a fresh view of
>>> the database, so why would the values differ?
>>> 2) Why is this only an issue in destroy_nat_entries()? There are several
>>> other places in the code where we iterate over the number of nat entries
>>> using od->nbr->n_nat. Why are those not affected?
>>> 3) How does this patch address that issue? The patch just sets the
>>> ovn_datapath's n_nat_entries to be the same as the database's count,
>>> which according to the commit message, is not always accurate.
>>>
>>> Can you provide some clarity here? Maybe tell of a situation where
>>> od->nbr->n_nat is incorrect?
>>
>> You are absolutely correct as the details in the commit message are not
>> sufficient to understand. In fact, I had a hard time remembering the
>> reason myself!
>>
>> IIRC, on each iteration, we need to call en_runtime_run(). This needs to
>> initialize the runtime data .. but .. it also needs to destroy the
>> runtime data from the previous run. This may not be the best way to do
>> it, but the I-P framework doesn't have a convenient way to clear data
>> between runs.
>>
>> Consider an example in which we have completed iteration x, and started
>> iteration x+1. If we add a NAT entry between iteration x and iteration
>> x+1, od->nbr->n_nat will contain the updated value of n_nat as the
>> northbound record will have been updated. However, as we have not yet
>> (re)initialized the nat entries in od, od->n_nat_entries will be equal
>> to the previous value. These two values could then be different which
>> makes this loop invalid. Does this make sense? If so, shall I update the
>> commit message? How would you like me to proceed?
> 
> OK, this makes a lot more sense now. It makes sense that the issue 
> specifically would be seen when destroying datapaths and not at any 
> other point.
> 
> Here is my suggestion for how to proceed:
> 1) Update the commit message to give an explanation similar to what 
> you've given here.

I posted a new series and added the comment.
> 2) Correct the finding that I just found right now and that I mention 
> down below.

I forgot to do this, I will fix in v2. Also, I am surprised I didn't see
this as I though I compiled with --enable-Werror.
> 
>>
>>>
>>> On 9/3/21 8:21 AM, Mark Gray wrote:
>>>> destroy_nat_entries() iterates over nat_entries using the
>>>> number of NAT entries from the NB database. When using I-P,
>>>> this behaviour is incorrect as the number of NAT entries in
>>>> the NBDB may differ from that stored in 'struct ovn_datapath'
>>>> causing unexpected behaviour.
>>>>
>>>> Signed-off-by: Mark Gray 
>>>> ---
>>>>northd/northd.c | 5 -
>>>>1 file changed, 4 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/northd/northd.c b/northd/northd.c
>>>> index 724baa3994d5..829c4479f14b 100644
>>>> --- a/northd/northd.c
>>>> +++ b/northd/northd.c
>>>> @@ -605,6 +605,8 @@ struct ovn_datapath {
>>>>
>>>>/* NAT entries configured on the router. */
>>>>struct ovn_nat *nat_entries;
>>>> +size_t n_nat_entries;
>>>> +
> 
> n_nat_entries is declared and never used in this function.
> 
>>>>bool has_distributed_nat;
>>>>
>>>>/* Set of nat external ips on the router. */
>>>> @@ -789,6 +791,7 @@ init_nat_entries(struct ovn_datapath *od)
>>>>od->has_distributed_nat = true;
>>>>}
>>>>}
>>>> +od->n_nat_entries = od->nbr->n_nat;
>>>>}
>>>>
>>>>static void
>>>> @@ -802,7 +805,7 @@ destroy_nat_entries(struct ovn_datapath *od)
>>>>destroy_lport_addresses(>dnat_force_snat_addrs);
>>>>destroy_lport_addresses(>lb_force_snat_addrs);
>>>>
>>>> -for (size_t i = 0; i < od->nbr->n_nat; i++) {
>>>> +for (size_t i = 0; i < od->n_nat_entries; i++) {
>>>>destroy_lport_addresses(>nat_entries[i].ext_addrs);
>>>>}
>>>>}
>>>>
>>>
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 5/7] northd: Introduce struct northd_data

2021-09-29 Thread Mark Gray
'struct northd_data' is used to hold the output data from the
incremental processing node 'en_northd'. This will be used, in
a later commit, as the input data to 'en_lflow'. In order to achieve
this, we refactor in the following way:

* Introduce northd_init() which initializes this data.
* Introduce northd_destroy() which clears this data for a new iteration.
* Introduce northd_indices_create() which does a one-time creation of
  indices for number of tables needed by northd.
* Remove 'ovn_internal_version' from the context passed to northd
  as it can be determined within northd using ovn_get_internal_version.
* Remove 'use_parallel_build' from the context passed to northd
  as it can be determined within northd using can_parallelize_hashes().
* Refactor northd.c to use 'struct northd_data' where applicable.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c  |  28 -
 northd/en-northd.h  |   4 +
 northd/northd.c | 274 
 northd/northd.h |  27 -
 northd/ovn-northd.c |  28 +
 5 files changed, 202 insertions(+), 159 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index 8dec51535af0..1b206521e152 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -20,26 +20,46 @@
 
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
+#include "openvswitch/list.h" /* TODO This is needed for ovn-parallel-hmap.h.
+   * lib/ovn-parallel-hmap.h should be updated
+   * to include this dependency itself */
+#include "lib/ovn-parallel-hmap.h"
 #include "northd.h"
+#include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
 
-void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+void en_northd_run(struct engine_node *node, void *data)
 {
 const struct engine_context *eng_ctx = engine_get_context();
 struct northd_idl_context *ctx = eng_ctx->client_ctx;
-ovn_db_run(ctx);
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
 
+northd_destroy(northd_data);
+northd_init(northd_data);
+
+northd_run(ctx, northd_data);
 engine_set_node_state(node, EN_UPDATED);
 
 }
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
- struct engine_arg *arg OVS_UNUSED)
+ struct engine_arg *arg)
 {
-return NULL;
+struct ed_type_northd *data = xmalloc(sizeof *data);
+data->data = xmalloc(sizeof *data->data);
+
+data->data->use_parallel_build = can_parallelize_hashes(false);
+northd_indices_create(data->data, arg->sb_idl);
+northd_init(data->data);
+
+return data;
 }
 
 void en_northd_cleanup(void *data OVS_UNUSED)
 {
+struct northd_data *northd_data = ((struct ed_type_northd *)data)->data;
+
+northd_destroy(northd_data);
+free(northd_data);
 }
diff --git a/northd/en-northd.h b/northd/en-northd.h
index 0e7f76245e69..da386298d821 100644
--- a/northd/en-northd.h
+++ b/northd/en-northd.h
@@ -9,6 +9,10 @@
 
 #include "lib/inc-proc-eng.h"
 
+struct ed_type_northd {
+struct northd_data *data;
+};
+
 void en_northd_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED);
 void *en_northd_init(struct engine_node *node OVS_UNUSED,
  struct engine_arg *arg);
diff --git a/northd/northd.c b/northd/northd.c
index 7c5948504a9b..d236e0361885 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -2853,6 +2853,7 @@ chassis_group_list_changed(
 
 static void
 sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
+   struct northd_data *data,
const struct nbrec_ha_chassis_group *nb_ha_grp,
struct ovsdb_idl_index *sbrec_chassis_by_name,
const struct sbrec_port_binding *pb)
@@ -2860,7 +2861,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 bool new_sb_chassis_group = false;
 const struct sbrec_ha_chassis_group *sb_ha_grp =
 ha_chassis_group_lookup_by_name(
-ctx->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
+data->sbrec_ha_chassis_grp_by_name, nb_ha_grp->name);
 
 if (!sb_ha_grp) {
 sb_ha_grp = sbrec_ha_chassis_group_insert(ctx->ovnsb_txn);
@@ -2906,6 +2907,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_idl_context 
*ctx,
 static void
 copy_gw_chassis_from_nbrp_to_sbpb(
 struct northd_idl_context *ctx,
+struct northd_data *data,
 struct ovsdb_idl_index *sbrec_chassis_by_name,
 const struct nbrec_logical_router_port *lrp,
 const struct sbrec_port_binding *port_binding)
@@ -2915,7 +2917,7 @@ copy_gw_chassis_from_nbrp_to_sbpb(
  * for the distributed gateway router port. */
 const struct sbrec_ha_chassis_group *sb_ha_chassis_gr

[ovs-dev] [PATCH ovn 7/7] en_lflow: Generate logical flows

2021-09-29 Thread Mark Gray
Generate logical flows using 'en_flow' incremental processing node.
This node uses output data from 'en_northd' in order to generate
logical flows.

Signed-off-by: Mark Gray 
---
 northd/en-lflow.c | 12 
 northd/northd.c   |  6 +-
 northd/northd.h   |  1 +
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/northd/en-lflow.c b/northd/en-lflow.c
index 46072cb0162e..e24c00e039c3 100644
--- a/northd/en-lflow.c
+++ b/northd/en-lflow.c
@@ -23,12 +23,24 @@
 
 #include "lib/inc-proc-eng.h"
 #include "northd.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
+#include "timeval.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_lflow);
 
 void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
 {
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
+
+struct ed_type_northd *northd_data = engine_get_input_data("northd", node);
+
+stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+build_lflows(ctx, northd_data->data);
+stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
+
 engine_set_node_state(node, EN_UPDATED);
 }
 void *en_lflow_init(struct engine_node *node OVS_UNUSED,
diff --git a/northd/northd.c b/northd/northd.c
index 6699b8a3ffc1..94620d243dec 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -13209,8 +13209,7 @@ static bool reset_parallel = false;
 
 /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database,
  * constructing their contents based on the OVN_NB database. */
-static void
-build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data)
 {
 struct hmap lflows;
 
@@ -14396,9 +14395,6 @@ ovnnb_db_run(struct northd_data *data,
 build_meter_groups(ctx, >meter_groups);
 build_bfd_table(ctx, >bfd_connections, >ports);
 stopwatch_stop(BUILD_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
-build_lflows(ctx, data);
-stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
 stopwatch_start(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
 ovn_update_ipv6_prefix(>ports);
 
diff --git a/northd/northd.h b/northd/northd.h
index d4bc5cf16541..07ea6899984f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -51,5 +51,6 @@ void northd_destroy(struct northd_data *data);
 void northd_init(struct northd_data *data);
 void northd_indices_create(struct northd_data *data,
struct ovsdb_idl *ovnsb_idl);
+void build_lflows(struct northd_idl_context *ctx, struct northd_data *data);
 
 #endif /* NORTHD_H */
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 6/7] northd: Add lflow node

2021-09-29 Thread Mark Gray
Add an additional node that initially does nothing. This serves as a
template for how to add a new node. This node is inserted after
the northd_node.

This node will be updated in a later commit to generate logical
flows for the SBDB.

Signed-off-by: Mark Gray 
---
 northd/automake.mk   |  2 ++
 northd/en-lflow.c| 42 
 northd/en-lflow.h| 16 +++
 northd/inc-proc-northd.c |  5 -
 northd/northd.c  |  2 --
 5 files changed, 64 insertions(+), 3 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h

diff --git a/northd/automake.mk b/northd/automake.mk
index f0c1fb11c83a..4862ec7b7ff3 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -6,6 +6,8 @@ northd_ovn_northd_SOURCES = \
northd/ovn-northd.c \
northd/en-northd.c \
northd/en-northd.h \
+   northd/en-lflow.c \
+   northd/en-lflow.h \
northd/inc-proc-northd.c \
northd/inc-proc-northd.h \
northd/ipam.c \
diff --git a/northd/en-lflow.c b/northd/en-lflow.c
new file mode 100644
index ..46072cb0162e
--- /dev/null
+++ b/northd/en-lflow.c
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-lflow.h"
+#include "en-northd.h"
+
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_lflow);
+
+void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+engine_set_node_state(node, EN_UPDATED);
+}
+void *en_lflow_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+return NULL;
+}
+
+void en_lflow_cleanup(void *data OVS_UNUSED)
+{
+}
diff --git a/northd/en-lflow.h b/northd/en-lflow.h
new file mode 100644
index ..0e4d522ff3fe
--- /dev/null
+++ b/northd/en-lflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_LFLOW_H
+#define EN_LFLOW_H 1
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "lib/inc-proc-eng.h"
+
+void en_lflow_run(struct engine_node *node, void *data);
+void *en_lflow_init(struct engine_node *node, struct engine_arg *arg);
+void en_lflow_cleanup(void *data);
+
+#endif /* EN_LFLOW_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 572b8de6536a..519fc1d0cb46 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -25,6 +25,7 @@
 #include "openvswitch/vlog.h"
 #include "inc-proc-northd.h"
 #include "en-northd.h"
+#include "en-lflow.h"
 #include "util.h"
 
 VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
@@ -140,6 +141,7 @@ enum sb_engine_node {
 /* Define engine nodes for other nodes. They should be defined as static to
  * avoid sparse errors. */
 static ENGINE_NODE(northd, "northd");
+static ENGINE_NODE(lflow, "lflow");
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb)
@@ -204,13 +206,14 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_add_input(_northd, _sb_load_balancer, NULL);
 engine_add_input(_northd, _sb_bfd, NULL);
 engine_add_input(_northd, _sb_fdb, NULL);
+engine_add_input(_lflow, _northd, NULL);
 
 struct engine_arg engine_arg = {
 .nb_idl = nb->idl,
 .sb_idl = sb->idl,
 };
 
-engine_init(_northd, _arg);
+engine_init(_lflow, _arg);
 }
 
 void inc_proc_northd_run(struct northd_idl_context *ctx,
diff --git a/northd/northd.c b/northd/northd.c
index d236e0361885..6699b8a3ffc1 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -12881,7 +12881,6 @@ struct lflows_thread_pool {
 struct worker_pool *pool;
 };
 
-
 static void *
 build_lflows_thread(void *arg)
 {
@@ -14410,7 +14409,6 @@ ovnnb_db_run(struct northd_data *data,
 cleanup_stale_fdp_entries(ctx, >datapaths);
 bfd_cleanup_connections(ctx, >bfd_connections);
 stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
-
 }
 
 /* Stores the list of chassis which references an ha_chassis_group.
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 4/7] northd: Rename struct northd_context

2021-09-29 Thread Mark Gray
In order to prepare for a subsequent commit, rename
'struct northd_context' to 'struct northd_idl_context'. In
subsequent commits, 'struct northd_idl_context' will then be
used, only, to hold the IDL context required by northd.

Signed-off-by: Mark Gray 
---
 northd/en-northd.c   |  2 +-
 northd/inc-proc-northd.c |  2 +-
 northd/inc-proc-northd.h |  2 +-
 northd/northd.c  | 83 
 northd/northd.h  |  4 +-
 northd/ovn-northd.c  | 10 ++---
 6 files changed, 52 insertions(+), 51 deletions(-)

diff --git a/northd/en-northd.c b/northd/en-northd.c
index d310fa4dd31f..8dec51535af0 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -28,7 +28,7 @@ VLOG_DEFINE_THIS_MODULE(en_northd);
 void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
 {
 const struct engine_context *eng_ctx = engine_get_context();
-struct northd_context *ctx = eng_ctx->client_ctx;
+struct northd_idl_context *ctx = eng_ctx->client_ctx;
 ovn_db_run(ctx);
 
 engine_set_node_state(node, EN_UPDATED);
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 85baeb07d3d9..572b8de6536a 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -213,7 +213,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
 engine_init(_northd, _arg);
 }
 
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute) {
 engine_set_force_recompute(recompute);
 engine_init_run();
diff --git a/northd/inc-proc-northd.h b/northd/inc-proc-northd.h
index 09cb8f3b3a80..6ee056dc14f5 100644
--- a/northd/inc-proc-northd.h
+++ b/northd/inc-proc-northd.h
@@ -8,7 +8,7 @@
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
   struct ovsdb_idl_loop *sb);
-void inc_proc_northd_run(struct northd_context *ctx,
+void inc_proc_northd_run(struct northd_idl_context *ctx,
  bool recompute);
 void inc_proc_northd_cleanup(void);
 
diff --git a/northd/northd.c b/northd/northd.c
index b22c29f90de5..7c5948504a9b 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -1167,7 +1167,7 @@ ovn_datapath_update_external_ids(struct ovn_datapath *od)
 }
 
 static void
-join_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+join_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
struct ovs_list *sb_only, struct ovs_list *nb_only,
struct ovs_list *both, struct ovs_list *lr_list)
 {
@@ -1278,7 +1278,7 @@ is_vxlan_mode(struct ovsdb_idl *ovnsb_idl)
 }
 
 static uint32_t
-get_ovn_max_dp_key_local(struct northd_context *ctx)
+get_ovn_max_dp_key_local(struct northd_idl_context *ctx)
 {
 if (is_vxlan_mode(ctx->ovnsb_idl)) {
 /* OVN_MAX_DP_GLOBAL_NUM doesn't apply for vxlan mode. */
@@ -1288,7 +1288,7 @@ get_ovn_max_dp_key_local(struct northd_context *ctx)
 }
 
 static void
-ovn_datapath_allocate_key(struct northd_context *ctx,
+ovn_datapath_allocate_key(struct northd_idl_context *ctx,
   struct hmap *datapaths, struct hmap *dp_tnlids,
   struct ovn_datapath *od, uint32_t *hint)
 {
@@ -1334,7 +1334,7 @@ ovn_datapath_assign_requested_tnl_id(struct hmap 
*dp_tnlids,
  * Initializes 'datapaths' to contain a "struct ovn_datapath" for every logical
  * switch and router. */
 static void
-build_datapaths(struct northd_context *ctx, struct hmap *datapaths,
+build_datapaths(struct northd_idl_context *ctx, struct hmap *datapaths,
 struct ovs_list *lr_list)
 {
 struct ovs_list sb_only, nb_only, both;
@@ -2305,7 +2305,7 @@ tag_alloc_create_new_tag(struct hmap *tag_alloc_table,
 
 
 static void
-join_logical_ports(struct northd_context *ctx,
+join_logical_ports(struct northd_idl_context *ctx,
struct hmap *datapaths, struct hmap *ports,
struct hmap *chassis_qdisc_queues,
struct hmap *tag_alloc_table, struct ovs_list *sb_only,
@@ -2767,7 +2767,7 @@ sbpb_gw_chassis_needs_update(
 }
 
 static struct sbrec_ha_chassis *
-create_sb_ha_chassis(struct northd_context *ctx,
+create_sb_ha_chassis(struct northd_idl_context *ctx,
  const struct sbrec_chassis *chassis,
  const char *chassis_name, int priority)
 {
@@ -2852,7 +2852,7 @@ chassis_group_list_changed(
 }
 
 static void
-sync_ha_chassis_group_for_sbpb(struct northd_context *ctx,
+sync_ha_chassis_group_for_sbpb(struct northd_idl_context *ctx,
const struct nbrec_ha_chassis_group *nb_ha_grp,
struct ovsdb_idl_index *sbrec_chassis_by_name,
const struct sbrec_port_binding *pb)
@@ -2905,7 +2905,7 @@ sync_ha_chassis_group_for_sbpb(struct northd_context *ctx,
  */
 static void
 copy_gw_chassis_from_nbrp_to_sbpb(
-struct northd_context *c

[ovs-dev] [PATCH ovn 2/7] northd: Introduce incremental processing for northd

2021-09-29 Thread Mark Gray
Initial implementation adds a single node (northd). This single
node executes the northd processing pipeline but does not do so
incrementally.

In order to develop incremental processing for northd, the code
will be organised with a .c/.h file for each I-P node following
the naming convention en-.c/.h. These files will
contain definition of the node data, the main node processing
functions and change handlers (if any). The purpose of these nodes
will be coordination of the nodes work and implemention of the
relevant interfaces to plugin to the I-P framework. The actual
work that will be executed by the node will be organised into
a companion file or files. Ideally this file will follow the
naming convention of the node: e.g. en-.c is
associated with .c.

Initial node topology sees the northd node dependent on all DB
nodes. This will evolve over time.

Co-authored-by: Numan Siddique 
Signed-off-by: Numan Siddique 
Signed-off-by: Mark Gray 
---
 lib/inc-proc-eng.h   |  16 +++
 northd/automake.mk   |   4 +
 northd/en-northd.c   |  45 +++
 northd/en-northd.h   |  17 +++
 northd/inc-proc-northd.c | 254 +++
 northd/inc-proc-northd.h |  15 +++
 northd/northd.c  |  12 +-
 northd/northd.h  |   8 +-
 northd/ovn-northd.c  | 201 ---
 9 files changed, 489 insertions(+), 83 deletions(-)
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 1ccae559dff6..a3f5a7e64287 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -63,15 +63,22 @@
 #define ENGINE_MAX_INPUT 256
 #define ENGINE_MAX_OVSDB_INDEX 256
 
+#include 
+#include 
+
+#include "compiler.h"
+
 struct engine_context {
 struct ovsdb_idl_txn *ovs_idl_txn;
 struct ovsdb_idl_txn *ovnsb_idl_txn;
+struct ovsdb_idl_txn *ovnnb_idl_txn;
 void *client_ctx;
 };
 
 /* Arguments to be passed to the engine at engine_init(). */
 struct engine_arg {
 struct ovsdb_idl *sb_idl;
+struct ovsdb_idl *nb_idl;
 struct ovsdb_idl *ovs_idl;
 };
 
@@ -347,6 +354,11 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_FUNC_SB(TBL_NAME) \
 ENGINE_FUNC_OVSDB(sb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN NB DB */
+#define ENGINE_FUNC_NB(TBL_NAME) \
+ENGINE_FUNC_OVSDB(nb, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -360,6 +372,10 @@ static void en_##DB_NAME##_##TBL_NAME##_cleanup(void *data 
OVS_UNUSED) \
 #define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
 ENGINE_NODE_OVSDB(sb, "SB", TBL_NAME, TBL_NAME_STR);
 
+/* Macro to define an engine node which represents a table of OVN NB DB */
+#define ENGINE_NODE_NB(TBL_NAME, TBL_NAME_STR) \
+ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, TBL_NAME_STR);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
diff --git a/northd/automake.mk b/northd/automake.mk
index 35ad8c09d9ba..f0c1fb11c83a 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -4,6 +4,10 @@ northd_ovn_northd_SOURCES = \
northd/northd.c \
northd/northd.h \
northd/ovn-northd.c \
+   northd/en-northd.c \
+   northd/en-northd.h \
+   northd/inc-proc-northd.c \
+   northd/inc-proc-northd.h \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/en-northd.c b/northd/en-northd.c
new file mode 100644
index ..d310fa4dd31f
--- /dev/null
+++ b/northd/en-northd.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "en-northd.h"
+#include "lib/inc-proc-eng.h"
+#include "northd.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_northd);
+
+void en_northd_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+const struct engine_context *eng_ctx = engine_get_context();
+struct northd_context *ctx = eng_ctx->client_ctx;
+ovn_db_run(ctx);
+
+engine_set_node_state(node, EN_UPDATED);

[ovs-dev] [PATCH ovn 3/7] northd: Add n_nat_entries field to 'struct ovn_datapath'

2021-09-29 Thread Mark Gray
destroy_nat_entries() iterates over nat_entries using 'n_nat'
as the number of NAT entries from the NB database. This behaviour can be
incorrect as it assumes that there are 'n_nat' 'nat_entries'. 'struct
ovn_datapath' should maintain a count of 'nat_entries' in 'struct
ovn_datapath' rather than read the value from NBDB IDL to properly
account for the number of 'nat_entries'.

This issue becomes appatent when using destroy_nat_entries()
as part of an incremental processing loop:

Consider an example in which we have completed iteration x, and
started iteration x+1. If we add a NAT entry to NBDB between iteration x
and iteration x+1, od->nbr->n_nat will contain the updated value of
n_nat as the northbound record will have been updated. However, if
we do not (re)initialized the nat entries in od, od->n_nat_entries
could be equal to the previous value. This can cause destroy_nat_entries()
to loop over the wrong number of 'nat_entries' causing unexpected
behaviour.

Signed-off-by: Mark Gray 
---
 northd/northd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/northd/northd.c b/northd/northd.c
index c895eeb68b6d..b22c29f90de5 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -603,6 +603,8 @@ struct ovn_datapath {
 
 /* NAT entries configured on the router. */
 struct ovn_nat *nat_entries;
+size_t n_nat_entries;
+
 bool has_distributed_nat;
 
 /* Set of nat external ips on the router. */
@@ -787,6 +789,7 @@ init_nat_entries(struct ovn_datapath *od)
 od->has_distributed_nat = true;
 }
 }
+od->n_nat_entries = od->nbr->n_nat;
 }
 
 static void
@@ -800,7 +803,7 @@ destroy_nat_entries(struct ovn_datapath *od)
 destroy_lport_addresses(>dnat_force_snat_addrs);
 destroy_lport_addresses(>lb_force_snat_addrs);
 
-for (size_t i = 0; i < od->nbr->n_nat; i++) {
+for (size_t i = 0; i < od->n_nat_entries; i++) {
 destroy_lport_addresses(>nat_entries[i].ext_addrs);
 }
 }
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 1/7] inc-proc-eng: Allow definition of engine_node with global scope

2021-09-29 Thread Mark Gray
Refactor ENGINE_NODE() macro to not assign function pointers. This
allows ENGINE_NODE() to be used outside functions, creating an
engine_node with global scope (but can be statically defined within a file).
This allows more flexibility in how the I-P engine can be used as
engine nodes can be defined. Allow this is not explicitly required for
I-P it does allow for a cleaner code base as the node definitions can
be kept together outside any functions.

Additional function pointers (e.g. is_valid(), clear_tracked_data()),
may be assigned later, if required.

Signed-off-by: Mark Gray 
---
 controller/ovn-controller.c | 2 +-
 lib/inc-proc-eng.h  | 8 
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index a719beb0e615..1071966c321d 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -3218,7 +3218,7 @@ main(int argc, char *argv[])
 stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
 
 /* Define inc-proc-engine nodes. */
-ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones");
+ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones, "ct_zones");
 ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
 ENGINE_NODE(non_vif_data, "non_vif_data");
 ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index 859b30a71c86..1ccae559dff6 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -295,19 +295,19 @@ void engine_ovsdb_node_add_index(struct engine_node *, 
const char *name,
 .init = en_##NAME##_init, \
 .run = en_##NAME##_run, \
 .cleanup = en_##NAME##_cleanup, \
-.is_valid = en_##NAME##_is_valid, \
+.is_valid = NULL, \
 .clear_tracked_data = NULL, \
 };
 
 #define ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
-#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
+#define ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA_IS_VALID(NAME, NAME_STR) \
 ENGINE_NODE_CUSTOM_DATA(NAME, NAME_STR) \
-en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data;
+en_##NAME.clear_tracked_data = en_##NAME##_clear_tracked_data; \
+en_##NAME.is_valid = en_##NAME##_is_valid;
 
 #define ENGINE_NODE(NAME, NAME_STR) \
-static bool (*en_##NAME##_is_valid)(struct engine_node *node) = NULL; \
 ENGINE_NODE_DEF(NAME, NAME_STR)
 
 #define ENGINE_NODE_WITH_CLEAR_TRACK_DATA(NAME, NAME_STR) \
-- 
2.27.0

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 0/7] northd: Introduce incremental processing framework

2021-09-29 Thread Mark Gray
Add the 'inc-proc-eng' framework to northd. This does *not*
add any incremental processing at this stage but provides the
framework to do so. Even in this base configuration, we see an
advantage as northd no longer processes the databases if it has
been woken only to handle, for example, a unixctl command. This
can be seen below

$ ovn-appctl -t ovn-northd stopwatch/reset
$ for i in {1..10}; do ovn-appctl -t ovn-northd stopwatch/show >/dev/null; done
$ ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Statistics for 'ovnnb_db_run'
  Total samples: 0
  Maximum: 0 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 0.00 msec
  Long term average: 0.00 msec

Hopefully this starting point will allow others to discuss or contribute
changes to incrementally process some aspects of northd. We an also
decide if it is worth progressing with this in general.

Thanks,

Mark Gray (7):
  inc-proc-eng: Allow definition of engine_node with global scope
  northd: Introduce incremental processing for northd
  northd: Add n_nat_entries field to 'struct ovn_datapath'
  northd: Rename struct northd_context
  northd: Introduce struct northd_data
  northd: Add lflow node
  en_lflow: Generate logical flows

 controller/ovn-controller.c |   2 +-
 lib/inc-proc-eng.h  |  24 ++-
 northd/automake.mk  |   6 +
 northd/en-lflow.c   |  54 ++
 northd/en-lflow.h   |  16 ++
 northd/en-northd.c  |  65 +++
 northd/en-northd.h  |  21 +++
 northd/inc-proc-northd.c| 257 ++
 northd/inc-proc-northd.h|  15 ++
 northd/northd.c | 358 +++-
 northd/northd.h |  36 +++-
 northd/ovn-northd.c | 237 ++--
 12 files changed, 807 insertions(+), 284 deletions(-)
 create mode 100644 northd/en-lflow.c
 create mode 100644 northd/en-lflow.h
 create mode 100644 northd/en-northd.c
 create mode 100644 northd/en-northd.h
 create mode 100644 northd/inc-proc-northd.c
 create mode 100644 northd/inc-proc-northd.h

-- 
2.27.0


___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH] ovsdb-data: Deduplicate string atoms.

2021-09-24 Thread Mark Gray
On 24/09/2021 12:01, Ilya Maximets wrote:
> On 9/24/21 11:12, Mark Gray wrote:
>> On 23/09/2021 01:13, Ilya Maximets wrote:
>>> ovsdb-server spends a lot of time cloning atoms for various reasons,
>>> e.g. to create a diff of two rows or to clone a row to the transaction.
>>> All atoms, except for strings, contains a simple value that could be
>>> copied in efficient way, but duplicating strings every time has a
>>> significant performance impact.
>>>
>>> Introducing a new reference-counted structure 'ovsdb_atom_string'
>>> that allows to not copy strings every time, but just increase a
>>> reference counter.
>>>
>>> Changes in ovsdb/ovsdb-idlc.in are a bit brute-force-like, but I
>>> didn't manage to write anything better.  And this part is very hard
>>> to understand and debug, so maybe it's better to keep it in this
>>> more or less understandable shape.
>>>
>>> This change allows to increase transaction throughput in benchmarks
>>> up to 2x for standalone databases and 3x for clustered databases, i.e.
>>> number of transactions that ovsdb-server can handle per second.
>>> It also noticeably reduces memory consumption of ovsdb-server.
>>>
>>
>> Great!
>>
>>> Next step will be to consolidate this structure with json strings,
>>> so we will not need to duplicate strings while converting database
>>> objects to json and back.
>>>
>>> Signed-off-by: Ilya Maximets 
>>> ---
>>>
>>> There is a small conflict in lib/db-ctl-base.c with the 'set
>>> optimizations' patch-set, but it can be easily resolved if
>>> someone wants to try these patches together>
>>>  lib/db-ctl-base.c  |  11 +--
>>>  lib/ovsdb-cs.c |   2 +-
>>>  lib/ovsdb-data.c   |  45 ++-
>>>  lib/ovsdb-data.h   |  29 ++-
>>>  lib/ovsdb-idl.c|   3 +-
>>>  ovsdb/ovsdb-idlc.in| 179 -
>>>  ovsdb/ovsdb-server.c   |   6 +-
>>>  ovsdb/ovsdb-util.c |  16 ++--
>>>  ovsdb/rbac.c   |   8 +-
>>>  python/ovs/db/data.py  |  43 +++---
>>>  python/ovs/db/types.py |   7 +-
>>>  tests/test-ovsdb.c |  14 ++--
>>>  12 files changed, 244 insertions(+), 119 deletions(-)
>>>
>>> diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
>>> index 77cc76a9f..713487797 100644
>>> --- a/lib/db-ctl-base.c
>>> +++ b/lib/db-ctl-base.c
>>> @@ -247,15 +247,15 @@ record_id_equals(const union ovsdb_atom *name, enum 
>>> ovsdb_atomic_type type,
>>>   const char *record_id)
>>>  {
>>>  if (type == OVSDB_TYPE_STRING) {
>>> -if (!strcmp(name->string, record_id)) {
>>> +if (!strcmp(name->s->string, record_id)) {
>>>  return true;
>>>  }
>>>  
>>>  struct uuid uuid;
>>>  size_t len = strlen(record_id);
>>>  if (len >= 4
>>> -&& uuid_from_string(, name->string)
>>> -&& !strncmp(name->string, record_id, len)) {
>>> +&& uuid_from_string(, name->s->string)
>>> +&& !strncmp(name->s->string, record_id, len)) {
>>>  return true;
>>>  }
>>>  
>>> @@ -318,11 +318,12 @@ get_row_by_id(struct ctl_context *ctx,
>>>  if (!id->key) {
>>>  name = datum->n == 1 ? >keys[0] : NULL;
>>>  } else {
>>> -const union ovsdb_atom key_atom
>>> -= { .string = CONST_CAST(char *, id->key) };
>>> +union ovsdb_atom key_atom = {
>>> +.s = ovsdb_atom_string_create(CONST_CAST(char *, id->key)) 
>>> };
>>>  unsigned int i = ovsdb_datum_find_key(datum, _atom,
>>>OVSDB_TYPE_STRING);
>>>  name = i == UINT_MAX ? NULL : >values[i];
>>> +ovsdb_atom_destroy(_atom, OVSDB_TYPE_STRING);
>>>  }
>>>  if (!name) {
>>>  continue;
>>> diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c
>>> index 659d49dbf..fcb6fe1b3 100644
>>> --- a/lib/ovsdb-cs.c
>>> +++ b/lib/ovsdb-cs.c
>>> @@ -1833,7 +1833,7 @@ server_column_get_string(const struct server_row *row,
>>>  {
>>>  ovs_assert(server_columns[i

Re: [ovs-dev] [PATCH] ovsdb-data: Deduplicate string atoms.

2021-09-24 Thread Mark Gray
On 23/09/2021 01:13, Ilya Maximets wrote:
> ovsdb-server spends a lot of time cloning atoms for various reasons,
> e.g. to create a diff of two rows or to clone a row to the transaction.
> All atoms, except for strings, contains a simple value that could be
> copied in efficient way, but duplicating strings every time has a
> significant performance impact.
> 
> Introducing a new reference-counted structure 'ovsdb_atom_string'
> that allows to not copy strings every time, but just increase a
> reference counter.
> 
> Changes in ovsdb/ovsdb-idlc.in are a bit brute-force-like, but I
> didn't manage to write anything better.  And this part is very hard
> to understand and debug, so maybe it's better to keep it in this
> more or less understandable shape.
> 
> This change allows to increase transaction throughput in benchmarks
> up to 2x for standalone databases and 3x for clustered databases, i.e.
> number of transactions that ovsdb-server can handle per second.
> It also noticeably reduces memory consumption of ovsdb-server.
> 

Great!

> Next step will be to consolidate this structure with json strings,
> so we will not need to duplicate strings while converting database
> objects to json and back.
> 
> Signed-off-by: Ilya Maximets 
> ---
> 
> There is a small conflict in lib/db-ctl-base.c with the 'set
> optimizations' patch-set, but it can be easily resolved if
> someone wants to try these patches together>
>  lib/db-ctl-base.c  |  11 +--
>  lib/ovsdb-cs.c |   2 +-
>  lib/ovsdb-data.c   |  45 ++-
>  lib/ovsdb-data.h   |  29 ++-
>  lib/ovsdb-idl.c|   3 +-
>  ovsdb/ovsdb-idlc.in| 179 -
>  ovsdb/ovsdb-server.c   |   6 +-
>  ovsdb/ovsdb-util.c |  16 ++--
>  ovsdb/rbac.c   |   8 +-
>  python/ovs/db/data.py  |  43 +++---
>  python/ovs/db/types.py |   7 +-
>  tests/test-ovsdb.c |  14 ++--
>  12 files changed, 244 insertions(+), 119 deletions(-)
> 
> diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
> index 77cc76a9f..713487797 100644
> --- a/lib/db-ctl-base.c
> +++ b/lib/db-ctl-base.c
> @@ -247,15 +247,15 @@ record_id_equals(const union ovsdb_atom *name, enum 
> ovsdb_atomic_type type,
>   const char *record_id)
>  {
>  if (type == OVSDB_TYPE_STRING) {
> -if (!strcmp(name->string, record_id)) {
> +if (!strcmp(name->s->string, record_id)) {
>  return true;
>  }
>  
>  struct uuid uuid;
>  size_t len = strlen(record_id);
>  if (len >= 4
> -&& uuid_from_string(, name->string)
> -&& !strncmp(name->string, record_id, len)) {
> +&& uuid_from_string(, name->s->string)
> +&& !strncmp(name->s->string, record_id, len)) {
>  return true;
>  }
>  
> @@ -318,11 +318,12 @@ get_row_by_id(struct ctl_context *ctx,
>  if (!id->key) {
>  name = datum->n == 1 ? >keys[0] : NULL;
>  } else {
> -const union ovsdb_atom key_atom
> -= { .string = CONST_CAST(char *, id->key) };
> +union ovsdb_atom key_atom = {
> +.s = ovsdb_atom_string_create(CONST_CAST(char *, id->key)) };
>  unsigned int i = ovsdb_datum_find_key(datum, _atom,
>OVSDB_TYPE_STRING);
>  name = i == UINT_MAX ? NULL : >values[i];
> +ovsdb_atom_destroy(_atom, OVSDB_TYPE_STRING);
>  }
>  if (!name) {
>  continue;
> diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c
> index 659d49dbf..fcb6fe1b3 100644
> --- a/lib/ovsdb-cs.c
> +++ b/lib/ovsdb-cs.c
> @@ -1833,7 +1833,7 @@ server_column_get_string(const struct server_row *row,
>  {
>  ovs_assert(server_columns[index].type.key.type == OVSDB_TYPE_STRING);
>  const struct ovsdb_datum *d = >data[index];
> -return d->n == 1 ? d->keys[0].string : default_value;
> +return d->n == 1 ? d->keys[0].s->string : default_value;
>  }
>  
>  static bool
> diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
> index 1f491a98b..0ed8f01b6 100644
> --- a/lib/ovsdb-data.c
> +++ b/lib/ovsdb-data.c
> @@ -74,7 +74,7 @@ ovsdb_atom_init_default(union ovsdb_atom *atom, enum 
> ovsdb_atomic_type type)
>  break;
>  
>  case OVSDB_TYPE_STRING:
> -atom->string = xmemdup("", 1);
> +atom->s = ovsdb_atom_string_create_nocopy(xmemdup("", 1));
>  break;
>  
>  case OVSDB_TYPE_UUID:
> @@ -136,7 +136,7 @@ ovsdb_atom_is_default(const union ovsdb_atom *atom,
>  return atom->boolean == false;
>  
>  case OVSDB_TYPE_STRING:
> -return atom->string[0] == '\0';
> +return atom->s->string[0] == '\0';

perhaps a helper function would allow you to hide some of this from a
client. e.g.

char *ovsdb_atom_string_get(struct ovsdb_atom)
>  
>  case OVSDB_TYPE_UUID:
>  return uuid_is_zero(>uuid);
> @@ -172,7 +172,8 @@ ovsdb_atom_clone(union ovsdb_atom 

Re: [ovs-dev] [PATCH v2] ovsdb-server: Log database transactions for user requested tables.

2021-09-23 Thread Mark Gray
On 23/09/2021 11:20, Dumitru Ceara wrote:
> On 9/23/21 11:47 AM, Mark Gray wrote:
>> On 16/09/2021 16:37, Dumitru Ceara wrote:
>>> Add a new command, 'ovsdb-server/log-db-ops DB TABLE on|off', which
>>> allows the user to enable/disable transaction logging for specific
>>> databases and tables.
>>>
>>> By default, logging is disabled.  Once enabled, logs are generated
>>> with level INFO and are also rate limited.
>>>
>>> If used with care, this command can be useful in analyzing production
>>> deployment performance issues, allowing the user to pin point
>>> bottlenecks without the need to enable wider debug logs, e.g., jsonrpc.
>>>
>>> Signed-off-by: Dumitru Ceara 
>>> ---
>>> A sample use case is an ovn-kubernetes scaled deployment in which
>>> we're interesting in reducing time to bring up PODs (represented by
>>> OVN logical switch ports).  In order to determine exactly where the
>>> bottleneck is when provisioning PODs (CMS/ovn-nbctl/client
>>> IDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when
>>> operations happen at various places in the stack.
>>>
>>> Without this patch the only option for tracking when transactions
>>> happen in the Northbound database is to enable jsonrpc debug logs in
>>> ovsdb-server.  This generates a rather large amount of data.
>>>
>>> Instead, now, users would be able to just enable logging for the
>>> Logical_Switch_Port table getting more relevant and precise
>>> information.
>>>
>>> V2:
>>> - rebased (fixed conflicts in NEWS).
>>
>> Generally ok and I also did a quick test but I have a few comments on
>> the UI which wouldn't block an ACK and one small comment below in the code:
> 
> Thanks for the review!
> 
>>
>> * My personal preference would be that the syntax somewhat followed the
>> vlog/set one that seperates terms by ':'. Also a more memorable name.
>> For example tlog/set DB:TABLE:on or something like that but feel free to
>> choose to completely ignore me :) I just find it can sometimes be
>> difficult to remember syntax so I prefer some consistency.
> 
> Makes sense, I'll try to come up with something more consistent.
> 
>>
>> * One limititation is that I don't think we can add a log before a table
>> is created (i.e. to see the first entry). For example, let's say I want
>> to log the very first creation of a bridge using `ovs-vsctl add-br br0`.
>> Is there any way around it? I couldn't think of one.
> 
> I'm not sure I follow this point.  If you enable logging for the Bridge
> table before adding the first bridge you'll get the log, e.g., in an OVS
> sandbox:
> 
> $ ovs-appctl -t $PWD/sandbox/ovsdb-server.*.ctl ovsdb-server/log-db-ops
> Open_vSwitch Bridge on
> 
> $ ovs-vsctl show
> f43b960d-13f9-48d1-9898-703a3ac3f730
> 
> $ ovs-vsctl add-br br9
> 
> $ grep transaction sandbox/ovsdb-server.log
> 2021-09-23T09:57:53.426Z|7|transaction|INFO|table:Bridge,op:inserted,name:br9,flood_vlans:[],auto_attach:[],ports:[388811ab-13a9-4b50-92c6-10c00a8b5e42],stp_enable:false,rstp_enable:false,_uuid:8a59955c-2a3c-41d3-9e93-66845e51878b,fail_mode:[],rstp_status:{},flow_tables:{},_version:1603df48-3730-4324-a71b-1c9f7eadb865,netflow:[],datapath_type:"",controller:[],other_config:{},external_ids:{},status:{},ipfix:[],datapath_id:[],mirrors:[],mcast_snooping_enable:false,datapath_version:"",sflow:[],protocols:[]
> [...]

I just tested again and it does work. I think I must have specified
"bridge" instead of "Bridge". Sorry for the confusion.

>>
>> * Could you make the table and database names case-insensitive. For
>> example, I can do `ovs-vsctl list open` even though the table name is
>> actually Open_vSwitch? However, with this I need to specify the actual
>> table name.
>>
> 
> We can try but this would be a bit of an orthogonal change.  For example
> "ovs-appctl -t .. ovsdb-server/remove-db DB" only accepts case sensitive
> database names (due to case sensitive shash operations).  For using
> partial table names and/or, it would also be a more complex change.
> What you mentioned (ovs-vsctl) is actually implemented on the client
> side in db-ctl-base.c, get_table()/score_partial_match().

Ok, in that case, no need to update.

> 
>> * There is no way to list the tables that are currently 'on'. Something
>> like vlog/list.
> 
> Good idea, I'll add it!

Thanks

> 
>>
>> * Would it be useful to be able to specify which level to log to?: e.g.
>>
>> tlog/set D

Re: [ovs-dev] [PATCH v2] ovsdb-server: Log database transactions for user requested tables.

2021-09-23 Thread Mark Gray
On 23/09/2021 11:22, Dumitru Ceara wrote:
> On 9/23/21 12:03 PM, Mark Gray wrote:
>> On 23/09/2021 10:47, Mark Gray wrote:
>>> On 16/09/2021 16:37, Dumitru Ceara wrote:
>>>> Add a new command, 'ovsdb-server/log-db-ops DB TABLE on|off', which
>>>> allows the user to enable/disable transaction logging for specific
>>>> databases and tables.
>>>>
>>>> By default, logging is disabled.  Once enabled, logs are generated
>>>> with level INFO and are also rate limited.
>>>>
>>>> If used with care, this command can be useful in analyzing production
>>>> deployment performance issues, allowing the user to pin point
>>>> bottlenecks without the need to enable wider debug logs, e.g., jsonrpc.
>>>>
>>>> Signed-off-by: Dumitru Ceara 
>>>> ---
>>>> A sample use case is an ovn-kubernetes scaled deployment in which
>>>> we're interesting in reducing time to bring up PODs (represented by
>>>> OVN logical switch ports).  In order to determine exactly where the
>>>> bottleneck is when provisioning PODs (CMS/ovn-nbctl/client
>>>> IDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when
>>>> operations happen at various places in the stack.
>>>>
>>>> Without this patch the only option for tracking when transactions
>>>> happen in the Northbound database is to enable jsonrpc debug logs in
>>>> ovsdb-server.  This generates a rather large amount of data.
>>>>
>>>> Instead, now, users would be able to just enable logging for the
>>>> Logical_Switch_Port table getting more relevant and precise
>>>> information.
>>>>
>>>> V2:
>>>> - rebased (fixed conflicts in NEWS).
>>> Generally ok and I also did a quick test but I have a few comments on
>>> the UI which wouldn't block an ACK and one small comment below in the code:
>>>
>>> * My personal preference would be that the syntax somewhat followed the
>>> vlog/set one that seperates terms by ':'. Also a more memorable name.
>>> For example tlog/set DB:TABLE:on or something like that but feel free to
>>> choose to completely ignore me :) I just find it can sometimes be
>>> difficult to remember syntax so I prefer some consistency.
>>>
>>> * One limititation is that I don't think we can add a log before a table
>>> is created (i.e. to see the first entry). For example, let's say I want
>>> to log the very first creation of a bridge using `ovs-vsctl add-br br0`.
>>> Is there any way around it? I couldn't think of one.
>>>
>>> * Could you make the table and database names case-insensitive. For
>>> example, I can do `ovs-vsctl list open` even though the table name is
>>> actually Open_vSwitch? However, with this I need to specify the actual
>>> table name.
>>>
>>> * There is no way to list the tables that are currently 'on'. Something
>>> like vlog/list.
>>>
>>> * Would it be useful to be able to specify which level to log to?: e.g.
>>>
>>> tlog/set DB:TABLE:info
>>>
>>> * Would it be useful to have a non-verbose mode that only states that an
>>> insert/delete/update happened?
>>>
>>
>> Also, do we need to document this somewhere? I am not sure.
>>
> 
> I'm not sure where though..  I couldn't find documentation (apart from
> occasional mentions in the NEWS file) for the other "ovsdb-server/..."
> appctl commands.
> 

Maybe /ovsdb/ovsdb-server.1 ?

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn-northd: Virtual port add ND/ARP responder flows for IPv6 VIPs.

2021-09-23 Thread Mark Gray
On 20/09/2021 14:20, mh...@redhat.com wrote:
> From: Mohammad Heib 
> 
> currently ovn-northd only handle virtual ports with VIP IPv4 and ignores
> virtual ports with VIP IPv6.
> 
> This patch adds support for virtual ports with VIP IPv6 by adding
> lflows to the lsp_in_arp_rsp logical switch pipeline.
> Those lflows handle Neighbor Solicitations and Neighbor Advertisement requests
> that target the virtual port VIPs and bind the virtual port to the desired 
> VIF.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2003091
> Fixes: 054f4c85c413 ("Add a new logical switch port type - 'virtual'")
> Signed-off-by: Mohammad Heib 
> ---
>  northd/northd.c | 52 +++--
>  1 file changed, 42 insertions(+), 10 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.c
> index d1b87891c..d85036dcc 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -7386,16 +7386,30 @@ build_lswitch_arp_nd_responder_known_ips(struct 
> ovn_port *op,
>   *  - ARP reply from the virtual ip which belongs to a logical
>   *port of type 'virtual' and bind that port.
>   * */

I think this comment^ needs to be updated to reference ND

Also the comment above the function should be updated as the table
number is incorrect. You did not make this change but it would be good
to update.

> -ovs_be32 ip;
> +
> +union ip {
> +ovs_be32 ip;
> +ovs_u128 ipv6;
> +}ip;

I think you need to run `./utilities/checkpatch.py`? There seems to be a
few whitespace issues. For example: "s/}ip;/} ip;}"  and "s/else{/else
{". I think some of the line lengths are over the recommended
characters. I couldn't double-check on my machine because checkpatch,
for some reason, was hanging.

> +
>  const char *virtual_ip = smap_get(>nbsp->options,
>"virtual-ip");
>  const char *virtual_parents = smap_get(>nbsp->options,
> "virtual-parents");
> -if (!virtual_ip || !virtual_parents ||
> -!ip_parse(virtual_ip, )) {
> +if (!virtual_ip || !virtual_parents) {
>  return;
>  }
>  
> +bool is_ipv4 = strchr(virtual_ip, '.') ? true : false;
> +if (is_ipv4) {
> +if (!ip_parse(virtual_ip, )) {
> + return;
> +}
> +} else{
> +if (!ipv6_parse(virtual_ip, (struct in6_addr *)))
> + return;
> +}
> +
>  char *tokstr = xstrdup(virtual_parents);
>  char *save_ptr = NULL;
>  char *vparent;
> @@ -7408,13 +7422,31 @@ build_lswitch_arp_nd_responder_known_ips(struct 
> ovn_port *op,
>  continue;
>  }
>  
> -ds_clear(match);
> -ds_put_format(match, "inport == \"%s\" && "
> -  "((arp.op == 1 && arp.spa == %s && "
> -  "arp.tpa == %s) || (arp.op == 2 && "
> -  "arp.spa == %s))",
> -  vparent, virtual_ip, virtual_ip,
> -  virtual_ip);
> +if (is_ipv4) {
> +ds_clear(match);
> +ds_put_format(match, "inport == \"%s\" && "
> +"((arp.op == 1 && arp.spa == %s && "
> +"arp.tpa == %s) || (arp.op == 2 && "
> +"arp.spa == %s))",
> +vparent, virtual_ip, virtual_ip,
> +virtual_ip);
> +} else{
> +struct ipv6_netaddr na;
> +/* Find VIP multicast group */
> +in6_addr_solicited_node(_addr, (struct in6_addr 
> *));
> +inet_ntop(AF_INET6, _addr, na.sn_addr_s, sizeof 
> na.sn_addr_s);
> +
> +ds_clear(match);
> +ds_put_format(match, "inport == \"%s\" && "
> +"((nd_ns && ip6.dst == {%s, %s} && nd.target == 
> %s) ||"
> +"(nd_na && nd.target == %s))",
> +vparent,
> +virtual_ip,
> +na.sn_addr_s,
> +virtual_ip,
> +virtual_ip);
> +}
> +
>  ds_clear(actions);
>  ds_put_format(actions,
>  "bind_vport(%s, inport); "
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] ovsdb-server: Log database transactions for user requested tables.

2021-09-23 Thread Mark Gray
On 23/09/2021 10:47, Mark Gray wrote:
> On 16/09/2021 16:37, Dumitru Ceara wrote:
>> Add a new command, 'ovsdb-server/log-db-ops DB TABLE on|off', which
>> allows the user to enable/disable transaction logging for specific
>> databases and tables.
>>
>> By default, logging is disabled.  Once enabled, logs are generated
>> with level INFO and are also rate limited.
>>
>> If used with care, this command can be useful in analyzing production
>> deployment performance issues, allowing the user to pin point
>> bottlenecks without the need to enable wider debug logs, e.g., jsonrpc.
>>
>> Signed-off-by: Dumitru Ceara 
>> ---
>> A sample use case is an ovn-kubernetes scaled deployment in which
>> we're interesting in reducing time to bring up PODs (represented by
>> OVN logical switch ports).  In order to determine exactly where the
>> bottleneck is when provisioning PODs (CMS/ovn-nbctl/client
>> IDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when
>> operations happen at various places in the stack.
>>
>> Without this patch the only option for tracking when transactions
>> happen in the Northbound database is to enable jsonrpc debug logs in
>> ovsdb-server.  This generates a rather large amount of data.
>>
>> Instead, now, users would be able to just enable logging for the
>> Logical_Switch_Port table getting more relevant and precise
>> information.
>>
>> V2:
>> - rebased (fixed conflicts in NEWS).
> Generally ok and I also did a quick test but I have a few comments on
> the UI which wouldn't block an ACK and one small comment below in the code:
> 
> * My personal preference would be that the syntax somewhat followed the
> vlog/set one that seperates terms by ':'. Also a more memorable name.
> For example tlog/set DB:TABLE:on or something like that but feel free to
> choose to completely ignore me :) I just find it can sometimes be
> difficult to remember syntax so I prefer some consistency.
> 
> * One limititation is that I don't think we can add a log before a table
> is created (i.e. to see the first entry). For example, let's say I want
> to log the very first creation of a bridge using `ovs-vsctl add-br br0`.
> Is there any way around it? I couldn't think of one.
> 
> * Could you make the table and database names case-insensitive. For
> example, I can do `ovs-vsctl list open` even though the table name is
> actually Open_vSwitch? However, with this I need to specify the actual
> table name.
> 
> * There is no way to list the tables that are currently 'on'. Something
> like vlog/list.
> 
> * Would it be useful to be able to specify which level to log to?: e.g.
> 
> tlog/set DB:TABLE:info
> 
> * Would it be useful to have a non-verbose mode that only states that an
> insert/delete/update happened?
> 

Also, do we need to document this somewhere? I am not sure.

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] ovsdb-server: Log database transactions for user requested tables.

2021-09-23 Thread Mark Gray
On 16/09/2021 16:37, Dumitru Ceara wrote:
> Add a new command, 'ovsdb-server/log-db-ops DB TABLE on|off', which
> allows the user to enable/disable transaction logging for specific
> databases and tables.
> 
> By default, logging is disabled.  Once enabled, logs are generated
> with level INFO and are also rate limited.
> 
> If used with care, this command can be useful in analyzing production
> deployment performance issues, allowing the user to pin point
> bottlenecks without the need to enable wider debug logs, e.g., jsonrpc.
> 
> Signed-off-by: Dumitru Ceara 
> ---
> A sample use case is an ovn-kubernetes scaled deployment in which
> we're interesting in reducing time to bring up PODs (represented by
> OVN logical switch ports).  In order to determine exactly where the
> bottleneck is when provisioning PODs (CMS/ovn-nbctl/client
> IDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when
> operations happen at various places in the stack.
> 
> Without this patch the only option for tracking when transactions
> happen in the Northbound database is to enable jsonrpc debug logs in
> ovsdb-server.  This generates a rather large amount of data.
> 
> Instead, now, users would be able to just enable logging for the
> Logical_Switch_Port table getting more relevant and precise
> information.
> 
> V2:
> - rebased (fixed conflicts in NEWS).

Generally ok and I also did a quick test but I have a few comments on
the UI which wouldn't block an ACK and one small comment below in the code:

* My personal preference would be that the syntax somewhat followed the
vlog/set one that seperates terms by ':'. Also a more memorable name.
For example tlog/set DB:TABLE:on or something like that but feel free to
choose to completely ignore me :) I just find it can sometimes be
difficult to remember syntax so I prefer some consistency.

* One limititation is that I don't think we can add a log before a table
is created (i.e. to see the first entry). For example, let's say I want
to log the very first creation of a bridge using `ovs-vsctl add-br br0`.
Is there any way around it? I couldn't think of one.

* Could you make the table and database names case-insensitive. For
example, I can do `ovs-vsctl list open` even though the table name is
actually Open_vSwitch? However, with this I need to specify the actual
table name.

* There is no way to list the tables that are currently 'on'. Something
like vlog/list.

* Would it be useful to be able to specify which level to log to?: e.g.

tlog/set DB:TABLE:info

* Would it be useful to have a non-verbose mode that only states that an
insert/delete/update happened?

> ---
>  NEWS |  4 
>  ovsdb/ovsdb-server.c | 38 +
>  ovsdb/row.c  | 17 +++
>  ovsdb/row.h  |  1 +
>  ovsdb/table.c|  7 ++
>  ovsdb/table.h|  3 +++
>  ovsdb/transaction.c  | 51 
>  7 files changed, 121 insertions(+)
> 
> diff --git a/NEWS b/NEWS
> index 90f4b15902b8..d56329772276 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -10,6 +10,10 @@ Post-v2.16.0
> limiting behavior.
>   * Add hardware offload support for matching IPv4/IPv6 frag types
> (experimental).
> +   - OVSDB:
> + * New unixctl command 'ovsdb-server/log-db-ops DB TABLE on|off".
> +   If turned on, ovsdb-server will log (at level INFO and rate limited)
> +   all operations that are committed to table TABLE in the DB database.
>  
>  
>  v2.16.0 - 16 Aug 2021
> diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
> index 0b3d2bb71432..c48645f7e255 100644
> --- a/ovsdb/ovsdb-server.c
> +++ b/ovsdb/ovsdb-server.c
> @@ -115,6 +115,7 @@ static unixctl_cb_func ovsdb_server_list_remotes;
>  static unixctl_cb_func ovsdb_server_add_database;
>  static unixctl_cb_func ovsdb_server_remove_database;
>  static unixctl_cb_func ovsdb_server_list_databases;
> +static unixctl_cb_func ovsdb_server_log_db_ops;
>  
>  static void read_db(struct server_config *, struct db *);
>  static struct ovsdb_error *open_db(struct server_config *,
> @@ -443,6 +444,8 @@ main(int argc, char *argv[])
>   ovsdb_server_remove_database, _config);
>  unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0,
>   ovsdb_server_list_databases, _dbs);
> +unixctl_command_register("ovsdb-server/log-db-ops", "DB TABLE on|off",
> + 3, 3, ovsdb_server_log_db_ops, _dbs);
>  unixctl_command_register("ovsdb-server/perf-counters-show", "", 0, 0,
>   ovsdb_server_perf_counters_show, NULL);
>  unixctl_command_register("ovsdb-server/perf-counters-clear", "", 0, 0,
> @@ -1769,6 +1772,41 @@ ovsdb_server_list_databases(struct unixctl_conn *conn, 
> int argc OVS_UNUSED,
>  ds_destroy();
>  }
>  
> +static void
> +ovsdb_server_log_db_ops(struct unixctl_conn *conn, int argc OVS_UNUSED,
> +

Re: [ovs-dev] [PATCH v3 3/3] ovsdb-datum: Add function to apply diff in-place.

2021-09-23 Thread Mark Gray
On 23/09/2021 00:47, Ilya Maximets wrote:
> ovsdb_datum_apply_diff() is heavily used in ovsdb transactions, but
> it's linear in terms of number of comparisons.  And it also clones
> all the atoms along the way.  In most cases size of a diff is much
> smaller than the size of the original datum, this allows to perform
> the same operation in-place with only O(diff->n * log2(old->n))
> comparisons and O(old->n + diff->n) memory copies with memcpy.
> Using this function while applying diffs read from the storage gives
> a significant performance boost and allows to execute much more
> transactions per second.
> 
> Signed-off-by: Ilya Maximets 
> ---
> 
Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v3 2/3] ovsdb-data: Optimize subtraction of sets.

2021-09-23 Thread Mark Gray
On 23/09/2021 00:47, Ilya Maximets wrote:
> Current algorithm for ovsdb_datum_subtract looks like this:
> 
>   for-each atom in a:
>   if atom in b:
>   swap(atom, )
>   destroy(atom)
>   quicksort(a)
> 
> Complexity:
> 
>   Na * log2(Nb)  +  (Na - Nb) * log2(Na - Nb)
> Search  Comparisons for quicksort
> 
> It's not optimal, especially because Nb << Na in a vast majority of
> cases.
> 
> Reversing the search phase to look up atoms from 'b' in 'a', and
> closing gaps from deleted elements in 'a' by plain memory copy to
> avoid quicksort.
> 
> Resulted complexity:
> 
>   Nb * log2(Na)  +(Na - Nb)
> Search  Memory copies
> 
> Subtraction is heavily used while executing database transactions.
> For example, to remove one port from a logical switch in OVN.
> Complexity of such operation if original logical switch had 100 ports
> goes down from
> 
>  100 * log2(1)   = 100 comparisons for search and
>   99 * log2(99)  = 656 comparisons for quicksort
>--
>756 comparisons in total
> to only
> 
>1 * log2(100) = 7 comparisons for search
>+ memory copy of 99 * sizeof (union ovsdb_atom) bytes.
> 
> We could use memmove to close the gaps after removing atoms, but
> it will lead to 2 memory copies inside the call, while we can perform
> only one to the temporary 'result' and swap pointers.
> 
> Performance in cases, where sizes of 'a' and 'b' are comparable,
> should not change.  Cases with Nb >> Na should not happen in practice.
> 
> All in all, this change allows ovsdb-server to perform several times
> more transactions, that removes elements from sets, per second.
> 
> Signed-off-by: Ilya Maximets 
> ---
>  lib/ovsdb-data.c | 53 +---
>  1 file changed, 41 insertions(+), 12 deletions(-)
> 
> diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
> index 7f9ff83f4..5297f91ed 100644
> --- a/lib/ovsdb-data.c
> +++ b/lib/ovsdb-data.c
> @@ -2020,26 +2020,55 @@ ovsdb_datum_subtract(struct ovsdb_datum *a, const 
> struct ovsdb_type *a_type,
>   const struct ovsdb_datum *b,
>   const struct ovsdb_type *b_type)
>  {
> -bool changed = false;
> -size_t i;
> +unsigned int *idx, ai;
> +size_t n_idx;
>  
>  ovs_assert(a_type->key.type == b_type->key.type);
>  ovs_assert(a_type->value.type == b_type->value.type
> || b_type->value.type == OVSDB_TYPE_VOID);
>  
> -/* XXX The big-O of this could easily be improved. */
> -for (i = 0; i < a->n; ) {
> -unsigned int idx = ovsdb_datum_find(a, i, b, b_type);
> -if (idx != UINT_MAX) {
> -changed = true;
> -ovsdb_datum_remove_unsafe(a, i, a_type);
> -} else {
> -i++;
> +idx = xmalloc(b->n * sizeof *idx);
> +n_idx = 0;
> +for (size_t bi = 0; bi < b->n; bi++) {
> +ai = ovsdb_datum_find(b, bi, a, b_type);
> +if (ai == UINT_MAX) {
> +/* No such atom in 'a'. */
> +continue;
>  }
> +/* Not destroying right away since ovsdb_datum_find() will use them. 
> */
> +idx[n_idx++] = ai;
>  }
> -if (changed) {
> -ovsdb_datum_sort_assert(a, a_type->key.type);
> +if (!n_idx) {
> +free(idx);
> +return;
>  }
> +
> +struct ovsdb_datum result;
> +
> +ovsdb_datum_init_empty();
> +ovsdb_datum_reallocate(, a_type, a->n - n_idx);
> +
> +unsigned int start_idx = 0;
> +for (size_t i = 0; i < n_idx; i++) {
> +ai = idx[i];
> +
> +/* Destroying atom. */
> +ovsdb_atom_destroy(>keys[ai], a_type->key.type);
> +if (a_type->value.type != OVSDB_TYPE_VOID) {
> +ovsdb_atom_destroy(>values[ai], a_type->value.type);
> +}
> +
> +/* Copy non-removed atoms from 'a' to result. */
> +ovsdb_datum_push_unsafe(, a, start_idx, ai - start_idx, 
> a_type);
> +start_idx = idx[i] + 1;
> +}
> +/* Copying remaining atoms. */
> +ovsdb_datum_push_unsafe(, a, start_idx, a->n - start_idx, a_type);
> +a->n = 0;
> +
> +ovsdb_datum_swap(, a);
> +ovsdb_datum_destroy(, a_type);
> +free(idx);
>  }
>  
>  struct ovsdb_symbol_table *
> 


Acked-by: Mark D. Gray 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v3 1/3] ovsdb-data: Optimize union of sets.

2021-09-23 Thread Mark Gray
On 23/09/2021 00:47, Ilya Maximets wrote:
> Current algorithm of ovsdb_datum_union looks like this:
> 
>   for-each atom in b:
>   if not bin_search(a, atom):
>   push(a, clone(atom))
>   quicksort(a)
> 
> So, the complexity looks like this:
> 
>Nb * log2(Na)   +Nb +   (Na + Nb) * log2(Na + Nb)
>Comparisonsclones   Comparisons for quicksort
>for search
> 
> ovsdb_datum_union() is heavily used in database transactions while
> new element is added to a set.  For example, if new logical switch
> port is added to a logical switch in OVN.  This is a very common
> use case where CMS adds one new port to an existing switch that
> already has, let's say, 100 ports.  For this case ovsdb-server will
> have to perform:
> 
>1 * log2(100)  + 1 clone + 101 * log2(101)
>ComparisonsComparisons for
>for search   quicksort.
>~7   1~707
>Roughly 714 comparisons of atoms and 1 clone.
> 
> Since binary search can give us position, where new atom should go
> (it's the 'low' index after the search completion) for free, the
> logic can be re-worked like this:
> 
>   copied = 0
>   for-each atom in b:
>   desired_position = bin_search(a, atom)
>   push(result, a[ copied : desired_position - 1 ])
>   copied = desired_position
>   push(result, clone(atom))
>   push(result, a[ copied : Na ])
>   swap(a, result)
> 
> Complexity of this schema:
> 
>Nb * log2(Na)   +Nb + Na
>Comparisonsclones   memory copy on push
>for search
> 
> 'swap' is just a swap of a few pointers.  'push' is not a 'clone',
> but a simple memory copy of 'union ovsdb_atom'.
> 
> In general, this schema substitutes complexity of a quicksort
> with complexity of a memory copy of Na atom structures, where we're
> not even copying strings that these atoms are pointing to.
> 
> Complexity in the example above goes down from 714 comparisons
> to 7 comparisons and memcpy of 100 * sizeof (union ovsdb_atom) bytes.
> 
> General complexity of a memory copy should always be lower than
> complexity of a quicksort, especially because these copies usually
> performed in bulk, so this new schema should work faster for any input.
> 
> All in all, this change allows to execute several times more
> transactions per second for transactions that adds new entries to sets.
> 
> Alternatively, union can be implemented as a linear merge of two
> sorted arrays, but this will result in O(Na) comparisons, which
> is more than Nb * log2(Na) in common case, since Na is usually
> far bigger than Nb.  Linear merge will also mean per-atom memory
> copies instead of copying in bulk.
> 
> 'replace' functionality of ovsdb_datum_union() had no users, so it
> just removed.  But it can easily be added back if needed in the future.
> 
> Signed-off-by: Ilya Maximets 
> ---
>  lib/db-ctl-base.c |  28 +++--
>  lib/ovsdb-data.c  | 103 ++
>  lib/ovsdb-data.h  |  10 ++---
>  lib/ovsdb-idl.c   |  29 ++---
>  ovsdb/mutation.c  |   2 +-
>  vswitchd/bridge.c |   6 +--
>  6 files changed, 105 insertions(+), 73 deletions(-)
> 
> diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
> index 77cc76a9f..3923683fd 100644
> --- a/lib/db-ctl-base.c
> +++ b/lib/db-ctl-base.c
> @@ -314,15 +314,18 @@ get_row_by_id(struct ctl_context *ctx,
>  row, id->name_column, key, value);
>  
>  /* Extract the name from the column. */
> -const union ovsdb_atom *name;
> +const union ovsdb_atom *name = NULL;
>  if (!id->key) {
>  name = datum->n == 1 ? >keys[0] : NULL;
>  } else {
>  const union ovsdb_atom key_atom
>  = { .string = CONST_CAST(char *, id->key) };
> -unsigned int i = ovsdb_datum_find_key(datum, _atom,
> -  OVSDB_TYPE_STRING);
> -name = i == UINT_MAX ? NULL : >values[i];
> +unsigned int i;
> +
> +if (ovsdb_datum_find_key(datum, _atom,
> + OVSDB_TYPE_STRING, )) {
> +name = >values[i];
> +}
>  }
>  if (!name) {
>  continue;
> @@ -819,14 +822,14 @@ check_condition(const struct ovsdb_idl_table_class 
> *table,
>  goto out;
>  }
>  
> -idx = ovsdb_datum_find_key(have_datum,
> -   _key, column->type.key.type);
> -if (idx == UINT_MAX && !is_set_operator(operator)) {
> +bool found = ovsdb_datum_find_key(have_datum, _key,
> +  column->type.key.type, );
> +if (!found && !is_set_operator(operator)) {
>  retval = false;
>  } else {
>  struct ovsdb_datum a;
>  
> -if (idx != UINT_MAX) {
> +if (found) {
>  a.n = 1;
>  a.keys = 

Re: [ovs-dev] [PATCH v2 2/2] ovsdb-data: Optimize subtraction of sets.

2021-09-23 Thread Mark Gray
On 22/09/2021 22:28, Ilya Maximets wrote:
> On 9/21/21 12:33, Mark Gray wrote:
>> On 17/09/2021 18:17, Ilya Maximets wrote:
>>> Current algorithm for ovsdb_datum_subtract looks like this:
>>>
>>>   for-each atom in a:
>>>   if atom in b:
>>>   swap(atom, )
>>>   destroy(atom)
>>>   quicksort(a)
>>>
>>> Complexity:
>>>
>>>   Na * log2(Nb)  +  (Na - Nb) * log2(Na - Nb)
>>> Search  Comparisons for quicksort
>>>
>>> It's not optimal, especially because Nb << Na in a vast majority of
>>> cases.
>>>
>>> Reversing the search phase to look up atoms from 'b' in 'a', and
>>> closing gaps from deleted elements in 'a' by plain memory copy to
>>> avoid quicksort.
>>>
>>> Resulted complexity:
>>>
>>>   Nb * log2(Na)  +(Na - Nb)
>>> Search  Memory copies
>>>
>>> Subtraction is heavily used while executing database transactions.
>>> For example, to remove one port from a logical switch in OVN.
>>> Complexity of such operation if original logical switch had 100 ports
>>> goes down from
>>>
>>>  100 * log2(1)   = 100 comparisons for search and
>>>   99 * log2(99)  = 656 comparisons for quicksort
>>>--
>>>756 comparisons in total
>>> to only
>>>
>>>1 * log2(100) = 7 comparisons for search
>>>+ memory copy of 99 * sizeof (union ovsdb_atom) bytes.
>>>
>>> We could use memmove to close the gaps after removing atoms, but
>>> it will lead to 2 memory copies inside the call, while we can perform
>>> only one to the temporary 'result' and swap pointers.
>>>
>>> Performance in cases, where sizes of 'a' and 'b' are comparable,
>>> should not change.  Cases with Nb >> Na should not happen in practice.
>>
>> It seems like we are optimizing for the more common case in which Na >>
>> Nb. Not sure if there are use cases in which the other case could bubble
>> up as a bottleneck. Could we try to assess which case we are in by
>> checking the size of the sets and then select the algorithm based on
>> that assessment? i.e. have two algorithms?
> 
> In general, case where Nb >> Na means that user wants to delete big
> number of elements from a small set.  This doesn't make much practical
> sense, so I'm not sure if we need to optimize this scenario.

Yeah, that makes sense.

> We can, sure, integrate switches for more optimal implementations
> and add these more optimal implementations for particular cases if
> we'll need them in the future.


> 
>>
>>>
>>> All in all, this change allows ovsdb-server to perform several times
>>> more transactions, that removes elements from sets, per second.
>>>
>>> Signed-off-by: Ilya Maximets 
>>> ---
>>>  lib/ovsdb-data.c | 52 +---
>>>  1 file changed, 40 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
>>> index 11bf95fed..b6129d6ba 100644
>>> --- a/lib/ovsdb-data.c
>>> +++ b/lib/ovsdb-data.c
>>> @@ -2019,26 +2019,54 @@ ovsdb_datum_subtract(struct ovsdb_datum *a, const 
>>> struct ovsdb_type *a_type,
>>>   const struct ovsdb_datum *b,
>>>   const struct ovsdb_type *b_type)
>>>  {
>>> -bool changed = false;
>>> -size_t i;
>>> +size_t i, ai, bi, n_idx;
>>> +size_t *idx;
>>>  
>>>  ovs_assert(a_type->key.type == b_type->key.type);
>>>  ovs_assert(a_type->value.type == b_type->value.type
>>> || b_type->value.type == OVSDB_TYPE_VOID);
>>>  
>>> -/* XXX The big-O of this could easily be improved. */
>>> -for (i = 0; i < a->n; ) {
>>> -unsigned int idx = ovsdb_datum_find(a, i, b, b_type);
>>> -if (idx != UINT_MAX) {
>>> -changed = true;
>>> -ovsdb_datum_remove_unsafe(a, i, a_type);
>>> -} else {
>>> -i++;
>>> +idx = xmalloc(b->n * sizeof *idx);
>>> +n_idx = 0;
>>> +for (bi = 0; bi < b->n; bi++) {
>>> +ai = ovsdb_datum_find(b, bi, a, b_type);
>>> +if (ai == UINT_MAX || (n_idx && ai <= idx[n_idx - 1])) {
>>
>> If b 

Re: [ovs-dev] [PATCH v2 1/2] ovsdb-data: Optimize union of sets.

2021-09-21 Thread Mark Gray
On 17/09/2021 18:17, Ilya Maximets wrote:
> Current algorithm of ovsdb_datum_union looks like this:
> 
>   for-each atom in b:
>   if not bin_search(a, atom):
>   push(a, clone(atom))
>   quicksort(a)
> 
> So, the complexity looks like this:
> 
>Nb * log2(Na)   +Nb +   (Na + Nb) * log2(Na + Nb)
>Comparisonsclones   Comparisons for quicksort
>for search
> 
> ovsdb_datum_union() is heavily used in database transactions while
> new element is added to a set.  For example, if new logical switch
> port is added to a logical switch in OVN.  This is a very common
> use case where CMS adds one new port to an existing switch that
> already has, let's say, 100 ports.  For this case ovsdb-server will
> have to perform:
> 
>1 * log2(100)  + 1 clone + 101 * log2(101)
>ComparisonsComparisons for
>for search   quicksort.
>~7   1~707
>Roughly 714 comparisons of atoms and 1 clone.
> 
> Since binary search can give us position, where new atom should go
> (it's the 'low' index after the search completion) for free, the
> logic can be re-worked like this:
> 
>   copied = 0
>   for-each atom in b:
>   desired_position = bin_search(a, atom)
>   push(result, a[ copied : desired_position - 1 ])
>   copied = desired_position
>   push(result, clone(atom))
>   push(result, a[ copied : Na ])
>   swap(a, result)
> 
> Complexity of this schema:
> 
>Nb * log2(Na)   +Nb + Na
>Comparisonsclones   memory copy on push
>for search
> 
> 'swap' is just a swap of a few pointers.  'push' is not a 'clone',
> but a simple memory copy of 'union ovsdb_atom'.
> 
> In general, this schema substitutes complexity of a quicksort
> with complexity of a memory copy of Na atom structures, where we're
> not even copying strings that these atoms are pointing to.
> 
> Complexity in the example above goes down from 714 comparisons
> to 7 comparisons and memcpy of 100 * sizeof (union ovsdb_atom) bytes.
> 
> General complexity of a memory copy should always be lower than
> complexity of a quicksort, especially because these copies usually
> performed in bulk, so this new schema should work faster for any input.
> 
> All in all, this change allows to execute several times more
> transactions per second for transactions that adds new entries to sets.
> 
> Alternatively, union can be implemented as a linear merge of two
> sorted arrays, but this will result in O(Na) comparisons, which
> is more than Nb * log2(Na) in common case, since Na is usually
> far bigger than Nb.  Linear merge will also mean per-atom memory
> copies instead of copying in bulk.
> 
> 'replace' functionality of ovsdb_datum_union() had no users, so it
> just removed.  But it can easily be added back if needed in the future.
> 
> Signed-off-by: Ilya Maximets 
> ---
>  lib/db-ctl-base.c | 10 +++---
>  lib/ovsdb-data.c  | 84 ---
>  lib/ovsdb-data.h  |  6 ++--
>  lib/ovsdb-idl.c   |  8 ++---
>  ovsdb/mutation.c  |  2 +-
>  vswitchd/bridge.c |  9 +++--
>  6 files changed, 77 insertions(+), 42 deletions(-)
> 
> diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
> index 77cc76a9f..f69868702 100644
> --- a/lib/db-ctl-base.c
> +++ b/lib/db-ctl-base.c
> @@ -321,7 +321,7 @@ get_row_by_id(struct ctl_context *ctx,
>  const union ovsdb_atom key_atom
>  = { .string = CONST_CAST(char *, id->key) };
>  unsigned int i = ovsdb_datum_find_key(datum, _atom,
> -  OVSDB_TYPE_STRING);
> +  OVSDB_TYPE_STRING, NULL);
>  name = i == UINT_MAX ? NULL : >values[i];
>  }
>  if (!name) {
> @@ -820,7 +820,7 @@ check_condition(const struct ovsdb_idl_table_class *table,
>  }
>  
>  idx = ovsdb_datum_find_key(have_datum,
> -   _key, column->type.key.type);
> +   _key, column->type.key.type, NULL);
>  if (idx == UINT_MAX && !is_set_operator(operator)) {
>  retval = false;
>  } else {
> @@ -993,7 +993,7 @@ cmd_get(struct ctl_context *ctx)
>  }
>  
>  idx = ovsdb_datum_find_key(datum, ,
> -   column->type.key.type);
> +   column->type.key.type, NULL);
>  if (idx == UINT_MAX) {
>  if (must_exist) {
>  ctl_error(
> @@ -1375,7 +1375,7 @@ set_column(const struct ovsdb_idl_table_class *table,
>  ovsdb_atom_destroy(, column->type.value.type);
>  
>  ovsdb_datum_union(, ovsdb_idl_read(row, column),
> -  >type, false);
> +  >type);
>  ovsdb_idl_txn_verify(row, column);
>  ovsdb_idl_txn_write(row, column, );
>  } else {
> @@ -1514,7 

Re: [ovs-dev] [PATCH v2 2/2] ovsdb-data: Optimize subtraction of sets.

2021-09-21 Thread Mark Gray
On 17/09/2021 18:17, Ilya Maximets wrote:
> Current algorithm for ovsdb_datum_subtract looks like this:
> 
>   for-each atom in a:
>   if atom in b:
>   swap(atom, )
>   destroy(atom)
>   quicksort(a)
> 
> Complexity:
> 
>   Na * log2(Nb)  +  (Na - Nb) * log2(Na - Nb)
> Search  Comparisons for quicksort
> 
> It's not optimal, especially because Nb << Na in a vast majority of
> cases.
> 
> Reversing the search phase to look up atoms from 'b' in 'a', and
> closing gaps from deleted elements in 'a' by plain memory copy to
> avoid quicksort.
> 
> Resulted complexity:
> 
>   Nb * log2(Na)  +(Na - Nb)
> Search  Memory copies
> 
> Subtraction is heavily used while executing database transactions.
> For example, to remove one port from a logical switch in OVN.
> Complexity of such operation if original logical switch had 100 ports
> goes down from
> 
>  100 * log2(1)   = 100 comparisons for search and
>   99 * log2(99)  = 656 comparisons for quicksort
>--
>756 comparisons in total
> to only
> 
>1 * log2(100) = 7 comparisons for search
>+ memory copy of 99 * sizeof (union ovsdb_atom) bytes.
> 
> We could use memmove to close the gaps after removing atoms, but
> it will lead to 2 memory copies inside the call, while we can perform
> only one to the temporary 'result' and swap pointers.
> 
> Performance in cases, where sizes of 'a' and 'b' are comparable,
> should not change.  Cases with Nb >> Na should not happen in practice.

It seems like we are optimizing for the more common case in which Na >>
Nb. Not sure if there are use cases in which the other case could bubble
up as a bottleneck. Could we try to assess which case we are in by
checking the size of the sets and then select the algorithm based on
that assessment? i.e. have two algorithms?

> 
> All in all, this change allows ovsdb-server to perform several times
> more transactions, that removes elements from sets, per second.
> 
> Signed-off-by: Ilya Maximets 
> ---
>  lib/ovsdb-data.c | 52 +---
>  1 file changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
> index 11bf95fed..b6129d6ba 100644
> --- a/lib/ovsdb-data.c
> +++ b/lib/ovsdb-data.c
> @@ -2019,26 +2019,54 @@ ovsdb_datum_subtract(struct ovsdb_datum *a, const 
> struct ovsdb_type *a_type,
>   const struct ovsdb_datum *b,
>   const struct ovsdb_type *b_type)
>  {
> -bool changed = false;
> -size_t i;
> +size_t i, ai, bi, n_idx;
> +size_t *idx;
>  
>  ovs_assert(a_type->key.type == b_type->key.type);
>  ovs_assert(a_type->value.type == b_type->value.type
> || b_type->value.type == OVSDB_TYPE_VOID);
>  
> -/* XXX The big-O of this could easily be improved. */
> -for (i = 0; i < a->n; ) {
> -unsigned int idx = ovsdb_datum_find(a, i, b, b_type);
> -if (idx != UINT_MAX) {
> -changed = true;
> -ovsdb_datum_remove_unsafe(a, i, a_type);
> -} else {
> -i++;
> +idx = xmalloc(b->n * sizeof *idx);
> +n_idx = 0;
> +for (bi = 0; bi < b->n; bi++) {
> +ai = ovsdb_datum_find(b, bi, a, b_type);
> +if (ai == UINT_MAX || (n_idx && ai <= idx[n_idx - 1])) {

If b and a are always sorted, will we ever hit the second clause (n_idx
&& ai <= idx[n_idx - 1])? For example, if the following elements are
equivalent

b0 -> a0
b1 -> a1
..
..

bi is always > bi-1 therefore ai is always greater than ai-1. If there
is still a chance that we will hit it, could you add a more detailed
comment?

> +/* No such atom in 'a' or it's already marked for removal. */
> +continue;
>  }
> +idx[n_idx++] = ai;
>  }
> -if (changed) {
> -ovsdb_datum_sort_assert(a, a_type->key.type);
> +if (!n_idx) {
> +free(idx);
> +return;
>  }
> +
> +struct ovsdb_datum result;
> +
> +ovsdb_datum_init_empty();
> +ovsdb_datum_reallocate(, a_type, a->n - n_idx);
> +
> +for (i = 0; i < n_idx; i++) {

Why don't you destroy the atoms in-place in the loop above (bi = 0; bi <
b->n; bi++). Is it because you have to ovsdb_datum_find() each time? If
so, maybe add a comment.

> +ai = idx[i];
> +
> +/* Destroying atom. */
> +ovsdb_atom_destroy(>keys[ai], a_type->key.type);
> +if (a_type->value.type != OVSDB_TYPE_VOID) {
> +ovsdb_atom_destroy(>values[ai], a_type->value.type);
> +}
> +
> +/* Copy non-removed atoms from 'a' to result. */
> +unsigned int start_idx = (i > 0) ? idx[i - 1] + 1 : 0;

It won't save many cycles but could you initialize 'start_idx' to 0
outside the loop and set it to 'idx[i] + 1' after the statement below?

> +ovsdb_datum_push_unsafe(, a, start_idx, ai - start_idx, 
> a_type);
> +}
> +/* Copying 

Re: [ovs-dev] [PATCH v6 ovn] controller: add datapath meter capability check

2021-09-17 Thread Mark Gray
On 17/09/2021 17:25, Lorenzo Bianconi wrote:
> Dump datapath meter capabilities before configuring meters in
> ovn-controller
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
> Changes since v5:
> - send new command only on reconnection
> Changes since v4:
> - move rconn setup in ovs_feature_support_update and rename it in
>   ovs_feature_support_run
> - drop ovs_feature_support_init()
> - rename ovs_feature_support_deinit in ovs_feature_support_destroy
> Changes since v3:
> - add missing rconn_run_wait() and rconn_recv_wait() at the end of swconn for
>   loop
> - cosmetics
> Changes since v2:
> - move meter capability logic in lib/features.c
> Changes since v1:
> - move rconn in ovn-controller to avoid concurrency issues
> ---
>  controller/ovn-controller.c |   7 +--
>  include/ovn/features.h  |   6 ++-
>  lib/actions.c   |   3 ++
>  lib/automake.mk |   1 +
>  lib/features.c  | 102 +++-
>  lib/test-ovn-features.c |   6 +--
>  tests/ovn.at|   4 +-
>  7 files changed, 119 insertions(+), 10 deletions(-)
> 
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index d98ebbbfa..aa7941eeb 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -3574,9 +3574,9 @@ main(int argc, char *argv[])
>   * 'br_int_dp' is valid only if an OVS transaction is possible.
>   */
>  if (ovs_idl_txn
> -&& ovs_feature_support_update(br_int_dp
> -  ? _int_dp->capabilities
> -  : NULL)) {
> +&& ovs_feature_support_run(br_int_dp ?
> +   _int_dp->capabilities : NULL,
> +   br_int ? br_int->name : NULL)) {
>  VLOG_INFO("OVS feature set changed, force recompute.");
>  engine_set_force_recompute(true);
>  }
> @@ -3903,6 +3903,7 @@ loop_done:
>  ovsdb_idl_loop_destroy(_idl_loop);
>  ovsdb_idl_loop_destroy(_idl_loop);
>  
> +ovs_feature_support_destroy();
>  free(ovs_remote);
>  service_stop();
>  
> diff --git a/include/ovn/features.h b/include/ovn/features.h
> index c35d59b14..d12a8eb0d 100644
> --- a/include/ovn/features.h
> +++ b/include/ovn/features.h
> @@ -28,13 +28,17 @@
>   */
>  enum ovs_feature_support_bits {
>  OVS_CT_ZERO_SNAT_SUPPORT_BIT,
> +OVS_DP_METER_SUPPORT_BIT,
>  };
>  
>  enum ovs_feature_value {
>  OVS_CT_ZERO_SNAT_SUPPORT = (1 << OVS_CT_ZERO_SNAT_SUPPORT_BIT),
> +OVS_DP_METER_SUPPORT = (1 << OVS_DP_METER_SUPPORT_BIT),
>  };
>  
> +void ovs_feature_support_destroy(void);
>  bool ovs_feature_is_supported(enum ovs_feature_value feature);
> -bool ovs_feature_support_update(const struct smap *ovs_capabilities);
> +bool ovs_feature_support_run(const struct smap *ovs_capabilities,
> + const char *br_name);
>  
>  #endif
> diff --git a/lib/actions.c b/lib/actions.c
> index c572e88ae..7cf6be308 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -87,6 +87,9 @@ encode_start_controller_op(enum action_opcode opcode, bool 
> pause,
>  oc->max_len = UINT16_MAX;
>  oc->reason = OFPR_ACTION;
>  oc->pause = pause;
> +if (!ovs_feature_is_supported(OVS_DP_METER_SUPPORT)) {
> +meter_id = NX_CTLR_NO_METER;
> +}
>  oc->meter_id = meter_id;
>  
>  struct action_header ah = { .opcode = htonl(opcode) };
> diff --git a/lib/automake.mk b/lib/automake.mk
> index ddfe33948..9f9f447d5 100644
> --- a/lib/automake.mk
> +++ b/lib/automake.mk
> @@ -2,6 +2,7 @@ lib_LTLIBRARIES += lib/libovn.la
>  lib_libovn_la_LDFLAGS = \
>  $(OVS_LTINFO) \
>  -Wl,--version-script=$(top_builddir)/lib/libovn.sym \
> +$(OVS_LIBDIR)/libopenvswitch.la \
>  $(AM_LDFLAGS)
>  lib_libovn_la_SOURCES = \
>   lib/acl-log.c \
> diff --git a/lib/features.c b/lib/features.c
> index fddf4c450..f15ec42bb 100644
> --- a/lib/features.c
> +++ b/lib/features.c
> @@ -18,7 +18,14 @@
>  #include 
>  
>  #include "lib/util.h"
> +#include "lib/dirs.h"
> +#include "socket-util.h"
> +#include "lib/vswitch-idl.h"
>  #include "openvswitch/vlog.h"
> +#include "openvswitch/ofpbuf.h"
> +#include "openvswitch/rconn.h"
> +#include "openvswitch/ofp-msgs.h"
> +#include "openvswitch/ofp-meter.h"
>  #include "ovn/features.h"
>  
>  VLOG_DEFINE_THIS_MODULE(features);
> @@ -40,11 +47,16 @@ static uint32_t supported_ovs_features;
>  
>  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
>  
> +/* ovs-vswitchd connection. */
> +static struct rconn *swconn;
> +static uint32_t conn_seq_no;
> +
>  static bool
>  ovs_feature_is_valid(enum ovs_feature_value feature)
>  {
>  switch (feature) {
>  case OVS_CT_ZERO_SNAT_SUPPORT:
> +case OVS_DP_METER_SUPPORT:
>  return true;
>  default:
>  return false;
> @@ -58,9 +70,93 @@ 

Re: [ovs-dev] [PATCH v5 ovn] controller: add datapath meter capability check

2021-09-17 Thread Mark Gray
On 17/09/2021 11:12, Lorenzo Bianconi wrote:
> Dump datapath meter capabilities before configuring meters in
> ovn-controller
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
> Changes since v4:
> - move rconn setup in ovs_feature_support_update and rename it in
>   ovs_feature_support_run
> - drop ovs_feature_support_init()
> - rename ovs_feature_support_deinit in ovs_feature_support_destroy
> Changes since v3:
> - add missing rconn_run_wait() and rconn_recv_wait() at the end of swconn for
>   loop
> - cosmetics
> Changes since v2:
> - move meter capability logic in lib/features.c
> Changes since v1:
> - move rconn in ovn-controller to avoid concurrency issues
> ---
>  controller/ovn-controller.c |  7 +--
>  include/ovn/features.h  |  6 ++-
>  lib/actions.c   |  3 ++
>  lib/automake.mk |  1 +
>  lib/features.c  | 95 -
>  lib/test-ovn-features.c |  6 +--
>  tests/ovn.at|  4 +-
>  7 files changed, 112 insertions(+), 10 deletions(-)
> 
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 0031a1035..3347396f8 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -3569,9 +3569,9 @@ main(int argc, char *argv[])
>   * 'br_int_dp' is valid only if an OVS transaction is possible.
>   */
>  if (ovs_idl_txn
> -&& ovs_feature_support_update(br_int_dp
> -  ? _int_dp->capabilities
> -  : NULL)) {
> +&& ovs_feature_support_run(br_int_dp ?
> +   _int_dp->capabilities : NULL,
> +   br_int ? br_int->name : NULL)) {
>  VLOG_INFO("OVS feature set changed, force recompute.");
>  engine_set_force_recompute(true);
>  }
> @@ -3898,6 +3898,7 @@ loop_done:
>  ovsdb_idl_loop_destroy(_idl_loop);
>  ovsdb_idl_loop_destroy(_idl_loop);
>  
> +ovs_feature_support_destroy();
>  free(ovs_remote);
>  service_stop();
>  
> diff --git a/include/ovn/features.h b/include/ovn/features.h
> index c35d59b14..d12a8eb0d 100644
> --- a/include/ovn/features.h
> +++ b/include/ovn/features.h
> @@ -28,13 +28,17 @@
>   */
>  enum ovs_feature_support_bits {
>  OVS_CT_ZERO_SNAT_SUPPORT_BIT,
> +OVS_DP_METER_SUPPORT_BIT,
>  };
>  
>  enum ovs_feature_value {
>  OVS_CT_ZERO_SNAT_SUPPORT = (1 << OVS_CT_ZERO_SNAT_SUPPORT_BIT),
> +OVS_DP_METER_SUPPORT = (1 << OVS_DP_METER_SUPPORT_BIT),
>  };
>  
> +void ovs_feature_support_destroy(void);
>  bool ovs_feature_is_supported(enum ovs_feature_value feature);
> -bool ovs_feature_support_update(const struct smap *ovs_capabilities);
> +bool ovs_feature_support_run(const struct smap *ovs_capabilities,
> + const char *br_name);
>  
>  #endif
> diff --git a/lib/actions.c b/lib/actions.c
> index c572e88ae..7cf6be308 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -87,6 +87,9 @@ encode_start_controller_op(enum action_opcode opcode, bool 
> pause,
>  oc->max_len = UINT16_MAX;
>  oc->reason = OFPR_ACTION;
>  oc->pause = pause;
> +if (!ovs_feature_is_supported(OVS_DP_METER_SUPPORT)) {
> +meter_id = NX_CTLR_NO_METER;
> +}
>  oc->meter_id = meter_id;
>  
>  struct action_header ah = { .opcode = htonl(opcode) };
> diff --git a/lib/automake.mk b/lib/automake.mk
> index ddfe33948..9f9f447d5 100644
> --- a/lib/automake.mk
> +++ b/lib/automake.mk
> @@ -2,6 +2,7 @@ lib_LTLIBRARIES += lib/libovn.la
>  lib_libovn_la_LDFLAGS = \
>  $(OVS_LTINFO) \
>  -Wl,--version-script=$(top_builddir)/lib/libovn.sym \
> +$(OVS_LIBDIR)/libopenvswitch.la \
>  $(AM_LDFLAGS)
>  lib_libovn_la_SOURCES = \
>   lib/acl-log.c \
> diff --git a/lib/features.c b/lib/features.c
> index fddf4c450..3ec2d26af 100644
> --- a/lib/features.c
> +++ b/lib/features.c
> @@ -18,7 +18,14 @@
>  #include 
>  
>  #include "lib/util.h"
> +#include "lib/dirs.h"
> +#include "socket-util.h"
> +#include "lib/vswitch-idl.h"
>  #include "openvswitch/vlog.h"
> +#include "openvswitch/ofpbuf.h"
> +#include "openvswitch/rconn.h"
> +#include "openvswitch/ofp-msgs.h"
> +#include "openvswitch/ofp-meter.h"
>  #include "ovn/features.h"
>  
>  VLOG_DEFINE_THIS_MODULE(features);
> @@ -40,11 +47,15 @@ static uint32_t supported_ovs_features;
>  
>  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
>  
> +/* ovs-vswitchd connection. */
> +static struct rconn *swconn;
> +
>  static bool
>  ovs_feature_is_valid(enum ovs_feature_value feature)
>  {
>  switch (feature) {
>  case OVS_CT_ZERO_SNAT_SUPPORT:
> +case OVS_DP_METER_SUPPORT:
>  return true;
>  default:
>  return false;
> @@ -58,9 +69,87 @@ ovs_feature_is_supported(enum ovs_feature_value feature)
>  return supported_ovs_features & 

Re: [ovs-dev] [PATCH v4 ovn] controller: add datapath meter capability check

2021-09-17 Thread Mark Gray
On 16/09/2021 23:16, Lorenzo Bianconi wrote:
> Dump datapath meter capabilities before configuring meters in
> ovn-controller

Thanks. Generally OK with this with one suggestion below. I'm not sure
if it will work but I think it follows the typical ovn/ovn pattern which
uses _run() functions in these loops.

> 
> Signed-off-by: Lorenzo Bianconi 
> ---
> Changes since v3:
> - add missing rconn_run_wait() and rconn_recv_wait() at the end of swconn for
>   loop
> - cosmetics
> Changes since v2:
> - move meter capability logic in lib/features.c
> Changes since v1:
> - move rconn in ovn-controller to avoid concurrency issues
> ---
>  controller/ovn-controller.c |  4 ++
>  include/ovn/features.h  |  4 ++
>  lib/actions.c   |  3 ++
>  lib/automake.mk |  1 +
>  lib/features.c  | 90 +
>  tests/ovn.at|  4 +-
>  6 files changed, 104 insertions(+), 2 deletions(-)
> 
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 0031a1035..22cb4b956 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -3523,6 +3523,9 @@ main(int argc, char *argv[])
> ovsrec_server_has_datapath_table(ovs_idl_loop.idl)
> ? _int_dp
> : NULL);
> +if (br_int) {
> +ovs_feature_support_init(br_int->name);
> +}
>  
>  /* Enable ACL matching for double tagged traffic. */
>  if (ovs_idl_txn) {
> @@ -3898,6 +3901,7 @@ loop_done:
>  ovsdb_idl_loop_destroy(_idl_loop);
>  ovsdb_idl_loop_destroy(_idl_loop);
>  
> +ovs_feature_support_deinit();
>  free(ovs_remote);
>  service_stop();
>  
> diff --git a/include/ovn/features.h b/include/ovn/features.h
> index c35d59b14..5259f2c69 100644
> --- a/include/ovn/features.h
> +++ b/include/ovn/features.h
> @@ -28,12 +28,16 @@
>   */
>  enum ovs_feature_support_bits {
>  OVS_CT_ZERO_SNAT_SUPPORT_BIT,
> +OVS_DP_METER_SUPPORT_BIT,
>  };
>  
>  enum ovs_feature_value {
>  OVS_CT_ZERO_SNAT_SUPPORT = (1 << OVS_CT_ZERO_SNAT_SUPPORT_BIT),
> +OVS_DP_METER_SUPPORT = (1 << OVS_DP_METER_SUPPORT_BIT),
>  };
>  
> +void ovs_feature_support_init(const char *br_name);
> +void ovs_feature_support_deinit(void);
>  bool ovs_feature_is_supported(enum ovs_feature_value feature);
>  bool ovs_feature_support_update(const struct smap *ovs_capabilities);
>  
> diff --git a/lib/actions.c b/lib/actions.c
> index c572e88ae..7cf6be308 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -87,6 +87,9 @@ encode_start_controller_op(enum action_opcode opcode, bool 
> pause,
>  oc->max_len = UINT16_MAX;
>  oc->reason = OFPR_ACTION;
>  oc->pause = pause;
> +if (!ovs_feature_is_supported(OVS_DP_METER_SUPPORT)) {
> +meter_id = NX_CTLR_NO_METER;
> +}
>  oc->meter_id = meter_id;
>  
>  struct action_header ah = { .opcode = htonl(opcode) };
> diff --git a/lib/automake.mk b/lib/automake.mk
> index ddfe33948..9f9f447d5 100644
> --- a/lib/automake.mk
> +++ b/lib/automake.mk
> @@ -2,6 +2,7 @@ lib_LTLIBRARIES += lib/libovn.la
>  lib_libovn_la_LDFLAGS = \
>  $(OVS_LTINFO) \
>  -Wl,--version-script=$(top_builddir)/lib/libovn.sym \
> +$(OVS_LIBDIR)/libopenvswitch.la \
>  $(AM_LDFLAGS)
>  lib_libovn_la_SOURCES = \
>   lib/acl-log.c \
> diff --git a/lib/features.c b/lib/features.c
> index fddf4c450..decb4d24c 100644
> --- a/lib/features.c
> +++ b/lib/features.c
> @@ -18,7 +18,14 @@
>  #include 
>  
>  #include "lib/util.h"
> +#include "lib/dirs.h"
> +#include "socket-util.h"
> +#include "lib/vswitch-idl.h"
>  #include "openvswitch/vlog.h"
> +#include "openvswitch/ofpbuf.h"
> +#include "openvswitch/rconn.h"
> +#include "openvswitch/ofp-msgs.h"
> +#include "openvswitch/ofp-meter.h"
>  #include "ovn/features.h"
>  
>  VLOG_DEFINE_THIS_MODULE(features);
> @@ -40,11 +47,15 @@ static uint32_t supported_ovs_features;
>  
>  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
>  
> +/* ovs-vswitchd connection. */
> +static struct rconn *swconn;
> +
>  static bool
>  ovs_feature_is_valid(enum ovs_feature_value feature)
>  {
>  switch (feature) {
>  case OVS_CT_ZERO_SNAT_SUPPORT:
> +case OVS_DP_METER_SUPPORT:
>  return true;
>  default:
>  return false;
> @@ -58,6 +69,81 @@ ovs_feature_is_supported(enum ovs_feature_value feature)
>  return supported_ovs_features & feature;
>  }
>  
> +static bool
> +ovs_feature_get_openflow_cap(void)
> +{
> +if (!swconn) {
> +return false;
> +}
> +
> +rconn_run(swconn);
> +if (!rconn_is_connected(swconn)) {
> +return false;
> +}
> +
> +bool ret = false;
> +/* dump datapath meter capabilities. */
> +struct ofpbuf *msg = ofpraw_alloc(OFPRAW_OFPST13_METER_FEATURES_REQUEST,
> +  rconn_get_version(swconn), 0);
> +rconn_send(swconn, msg, NULL);
> + 

Re: [ovs-dev] [PATCH ovn v5 0/2] northd: Split northd

2021-09-17 Thread Mark Gray
On 16/09/2021 21:47, Numan Siddique wrote:
> On Thu, Sep 16, 2021 at 3:06 PM Han Zhou  wrote:
>>
>> Acked-by: Han Zhou 
> 
> Thanks Mark G (and Mark M and Han).  I applied both the patches to the
> main branch.

Thanks!
> 
> Numan
> 
>>
>> On Thu, Sep 16, 2021 at 8:49 AM Mark Gray  wrote:
>>
>>> These commits reorganise the northd code base in preparation for potential
>>> inclusion
>>> of I-P for northd.
>>>
>>> Please note that this mainly involves moving code around with minimal
>>> code changes. However, due to tight coupling between ovn-northd.c and
>>> northd.c,
>>> some minor changes were needed. For reference, and to help reviews, please
>>> examine the following at a minimum:
>>>
>>> * Configuration of the probe interval in northd.c
>>> (ovsdb_idl_set_probe_interval())
>>> * Passing of "use_parallel_build" and "lflow_locks" from ovn-northd.c and
>>>   northd.c.
>>> * Update of "struct northd_context": additon of fields and move to .h file.
>>>
>>> The commits were (hopefully) structured in a way to make the review
>>> easier. As
>>> this change touches all of ovn-northd, any change to "master" will make a
>>> rebase
>>> necessary and probably difficult. Therefore, if the general ideas is OK,
>>> then
>>> it would be great if this series could be expedited to prevent many
>>> rebases!
>>>
>>> Thanks
>>>
>>> ---
>>> v2: Rebase
>>> v3: Rebase. Fixed compile-time error
>>> v4: Add additional commits which add framework for incremental processing
>>> in northd
>>> v5: Remove additional IP commits (
>>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-September/387763.html)
>>> Rebase
>>>
>>> Mark Gray (2):
>>>   ovn-northd: Rename ovn-northd.c to northd.c
>>>   northd: Split northd.c
>>>
>>>  Documentation/tutorials/ovn-openstack.rst |   154 +-
>>>  northd/automake.mk| 2 +
>>>  northd/lrouter.dl | 2 +-
>>>  northd/northd.c   | 14579 +++
>>>  northd/northd.h   |42 +
>>>  northd/ovn-northd.c   | 14880 +---
>>>  northd/ovn.rs | 2 +-
>>>  northd/ovn_northd.dl  | 2 +-
>>>  tests/ovn-northd.at   | 2 +-
>>>  9 files changed, 14871 insertions(+), 14794 deletions(-)
>>>  create mode 100644 northd/northd.c
>>>  create mode 100644 northd/northd.h
>>>
>>> --
>>> 2.27.0
>>>
>>>
>>>
>> ___
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v5 2/2] northd: Split northd.c

2021-09-16 Thread Mark Gray
This commit splits northd into two parts. One part, ovn-northd.c,
is responsible for the `ovn-northd` application, and the other is
responsible for northd processing.

This takes one step towards a more modular northd code base.

Signed-off-by: Mark Gray 
---
 northd/automake.mk  |2 +
 northd/northd.c | 1106 +-
 northd/northd.h |   42 ++
 northd/ovn-northd.c | 1107 +++
 4 files changed, 1167 insertions(+), 1090 deletions(-)
 create mode 100644 northd/northd.h
 create mode 100644 northd/ovn-northd.c

diff --git a/northd/automake.mk b/northd/automake.mk
index 306b533a486b..35ad8c09d9ba 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -2,6 +2,8 @@
 bin_PROGRAMS += northd/ovn-northd
 northd_ovn_northd_SOURCES = \
northd/northd.c \
+   northd/northd.h \
+   northd/ovn-northd.c \
northd/ipam.c \
northd/ipam.h
 northd_ovn_northd_LDADD = \
diff --git a/northd/northd.c b/northd/northd.c
index 2fc8b073f5a3..688a6e4efb53 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -14,17 +14,13 @@
 
 #include 
 
-#include 
 #include 
 #include 
 
 #include "bitmap.h"
-#include "command-line.h"
-#include "daemon.h"
 #include "dirs.h"
 #include "ipam.h"
 #include "openvswitch/dynamic-string.h"
-#include "fatal-signal.h"
 #include "hash.h"
 #include "hmapx.h"
 #include "openvswitch/hmap.h"
@@ -40,13 +36,12 @@
 #include "lib/ovn-util.h"
 #include "lib/lb.h"
 #include "memory.h"
-#include "ovs-numa.h"
+#include "northd.h"
 #include "lib/ovn-parallel-hmap.h"
 #include "ovn/actions.h"
 #include "ovn/features.h"
 #include "ovn/logical-fields.h"
 #include "packets.h"
-#include "openvswitch/poll-loop.h"
 #include "simap.h"
 #include "smap.h"
 #include "sset.h"
@@ -54,41 +49,12 @@
 #include "stopwatch.h"
 #include "lib/stopwatch-names.h"
 #include "stream.h"
-#include "stream-ssl.h"
 #include "timeval.h"
-#include "unixctl.h"
 #include "util.h"
 #include "uuid.h"
 #include "openvswitch/vlog.h"
 
-VLOG_DEFINE_THIS_MODULE(ovn_northd);
-
-static unixctl_cb_func ovn_northd_exit;
-static unixctl_cb_func ovn_northd_pause;
-static unixctl_cb_func ovn_northd_resume;
-static unixctl_cb_func ovn_northd_is_paused;
-static unixctl_cb_func ovn_northd_status;
-static unixctl_cb_func cluster_state_reset_cmd;
-
-struct northd_context {
-struct ovsdb_idl *ovnnb_idl;
-struct ovsdb_idl *ovnsb_idl;
-struct ovsdb_idl_txn *ovnnb_txn;
-struct ovsdb_idl_txn *ovnsb_txn;
-struct ovsdb_idl_index *sbrec_chassis_by_name;
-struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name;
-struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp;
-struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;
-};
-
-struct northd_state {
-bool had_lock;
-bool paused;
-};
-
-static const char *ovnnb_db;
-static const char *ovnsb_db;
-static const char *unixctl_path;
+VLOG_DEFINE_THIS_MODULE(northd);
 
 static bool controller_event_en;
 
@@ -110,12 +76,6 @@ static bool use_ct_inv_match = true;
 #define DEFAULT_PROBE_INTERVAL_MSEC 5000
 static int northd_probe_interval_nb = 0;
 static int northd_probe_interval_sb = 0;
-
-/* SSL options */
-static const char *ssl_private_key_file;
-static const char *ssl_certificate_file;
-static const char *ssl_ca_cert_file;
-
 #define MAX_OVN_TAGS 4096
 
 /* Pipeline stages. */
@@ -403,29 +363,6 @@ ovn_stage_to_datapath_type(enum ovn_stage stage)
 }
 }
 
-static void
-usage(void)
-{
-printf("\
-%s: OVN northbound management daemon\n\
-usage: %s [OPTIONS]\n\
-\n\
-Options:\n\
-  --ovnnb-db=DATABASE   connect to ovn-nb database at DATABASE\n\
-(default: %s)\n\
-  --ovnsb-db=DATABASE   connect to ovn-sb database at DATABASE\n\
-(default: %s)\n\
-  --dry-run start in paused state (do not commit db changes)\n\
-  --unixctl=SOCKET  override default control socket name\n\
-  -h, --helpdisplay this help message\n\
-  -o, --options list available options\n\
-  -V, --version display version information\n\
-", program_name, program_name, default_nb_db(), default_sb_db());
-daemon_usage();
-vlog_usage();
-stream_usage("database", true, true, false);
-}
-
 struct ovn_chassis_qdisc_queues {
 struct hmap_node key_node;
 uint32_t queue_id;
@@ -4360,7 +4297,7 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct 
ovn_datapath *od,
 static bool use_logical_dp_groups = false;
 static bool use_parallel_build = true;
 
-static struct hashrow_locks lflow_locks;
+static struct hashrow_locks *lflow_locks;
 
 

[ovs-dev] [PATCH ovn v5 1/2] ovn-northd: Rename ovn-northd.c to northd.c

2021-09-16 Thread Mark Gray
In order to seperate the northd processing logic from the ovn-northd
application logic, rename ovn-northd. In this way, we can recreate
ovn-northd.c with only the application logic.

Signed-off-by: Mark Gray 
---
 Documentation/tutorials/ovn-openstack.rst | 154 +++---
 northd/automake.mk|   2 +-
 northd/lrouter.dl |   2 +-
 northd/{ovn-northd.c => northd.c} |   4 +-
 northd/ovn.rs |   2 +-
 northd/ovn_northd.dl  |   2 +-
 tests/ovn-northd.at   |   2 +-
 7 files changed, 84 insertions(+), 84 deletions(-)
 rename northd/{ovn-northd.c => northd.c} (99%)

diff --git a/Documentation/tutorials/ovn-openstack.rst 
b/Documentation/tutorials/ovn-openstack.rst
index 3ab4a240c0f3..557d6284f710 100644
--- a/Documentation/tutorials/ovn-openstack.rst
+++ b/Documentation/tutorials/ovn-openstack.rst
@@ -777,7 +777,7 @@ address for ``a``.  Let's see what happens if we do::
   ...
   ingress(dp="n1", inport="ap")
   -
-   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
+   0. ls_in_port_sec_l2 (northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
   next;
   13. ls_in_l2_lkup: no match (implicit drop)
 
@@ -790,15 +790,15 @@ destination for ``b``::
   ...
   ingress(dp="n1", inport="ap")
   -
-   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
+   0. ls_in_port_sec_l2 (northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
   next;
-  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:99:7a:17, 
priority 50, uuid 57a4c46f
+  13. ls_in_l2_lkup (northd.c:3529): eth.dst == fa:16:3e:99:7a:17, priority 
50, uuid 57a4c46f
   outport = "bp";
   output;
 
   egress(dp="n1", inport="ap", outport="bp")
   --
-   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "bp" && eth.dst == 
{fa:16:3e:99:7a:17}, priority 50, uuid 8aa6426d
+   8. ls_out_port_sec_l2 (northd.c:3654): outport == "bp" && eth.dst == 
{fa:16:3e:99:7a:17}, priority 50, uuid 8aa6426d
   output;
   /* output to "bp", type "" */
 
@@ -1214,29 +1214,29 @@ as the output port::
   ...
   ingress(dp="n1", inport="ap")
   -
-   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
+   0. ls_in_port_sec_l2 (northd.c:3234): inport == "ap" && eth.src == 
{fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
   next;
-   1. ls_in_port_sec_ip (ovn-northd.c:2364): inport == "ap" && eth.src == 
fa:16:3e:a9:4c:c7 && ip4.src == {10.1.1.5}, priority 90, uuid 343af48c
+   1. ls_in_port_sec_ip (northd.c:2364): inport == "ap" && eth.src == 
fa:16:3e:a9:4c:c7 && ip4.src == {10.1.1.5}, priority 90, uuid 343af48c
   next;
-   3. ls_in_pre_acl (ovn-northd.c:2646): ip, priority 100, uuid 46c089e6
+   3. ls_in_pre_acl (northd.c:2646): ip, priority 100, uuid 46c089e6
   reg0[0] = 1;
   next;
-   5. ls_in_pre_stateful (ovn-northd.c:2764): reg0[0] == 1, priority 100, uuid 
d1941634
+   5. ls_in_pre_stateful (northd.c:2764): reg0[0] == 1, priority 100, uuid 
d1941634
   ct_next;
 
   ct_next(ct_state=est|trk /* default (use --ct to customize) */)
   ---
-   6. ls_in_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl && 
ct_label.blocked == 0 && (inport == "ap" && ip4), priority 2002, uuid a12b39f0
+   6. ls_in_acl (northd.c:2925): !ct.new && ct.est && !ct.rpl && 
ct_label.blocked == 0 && (inport == "ap" && ip4), priority 2002, uuid a12b39f0
   next;
-  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:f6:e2:8f, 
priority 50, uuid c43ead31
+  13. ls_in_l2_lkup (northd.c:3529): eth.dst == fa:16:3e:f6:e2:8f, priority 
50, uuid c43ead31
   outport = "17d870";
   output;
 
   egress(dp="n1", inport="ap", outport="17d870")
   --
-   1. ls_out_pre_acl (ovn-northd.c:2626): ip && outport == "17d870", priority 
110, uuid 60395450
+   1. ls_out_pre_acl (northd.c:2626): ip && outport == "17d870", priority 110, 
uuid 60395450
   next;
-   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "17d8

[ovs-dev] [PATCH ovn v5 0/2] northd: Split northd

2021-09-16 Thread Mark Gray
These commits reorganise the northd code base in preparation for potential 
inclusion
of I-P for northd.

Please note that this mainly involves moving code around with minimal
code changes. However, due to tight coupling between ovn-northd.c and northd.c,
some minor changes were needed. For reference, and to help reviews, please
examine the following at a minimum:

* Configuration of the probe interval in northd.c 
(ovsdb_idl_set_probe_interval())
* Passing of "use_parallel_build" and "lflow_locks" from ovn-northd.c and
  northd.c.
* Update of "struct northd_context": additon of fields and move to .h file.

The commits were (hopefully) structured in a way to make the review easier. As
this change touches all of ovn-northd, any change to "master" will make a rebase
necessary and probably difficult. Therefore, if the general ideas is OK, then
it would be great if this series could be expedited to prevent many rebases!

Thanks

---
v2: Rebase
v3: Rebase. Fixed compile-time error
v4: Add additional commits which add framework for incremental processing in 
northd
v5: Remove additional IP commits 
(https://mail.openvswitch.org/pipermail/ovs-dev/2021-September/387763.html)
Rebase

Mark Gray (2):
  ovn-northd: Rename ovn-northd.c to northd.c
  northd: Split northd.c

 Documentation/tutorials/ovn-openstack.rst |   154 +-
 northd/automake.mk| 2 +
 northd/lrouter.dl | 2 +-
 northd/northd.c   | 14579 +++
 northd/northd.h   |42 +
 northd/ovn-northd.c   | 14880 +---
 northd/ovn.rs | 2 +-
 northd/ovn_northd.dl  | 2 +-
 tests/ovn-northd.at   | 2 +-
 9 files changed, 14871 insertions(+), 14794 deletions(-)
 create mode 100644 northd/northd.c
 create mode 100644 northd/northd.h

-- 
2.27.0


___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn v4 7/7] northd: Add functionality to runtime node

2021-09-16 Thread Mark Gray
On 16/09/2021 08:08, Han Zhou wrote:
> On Fri, Sep 3, 2021 at 5:22 AM Mark Gray  wrote:
>>

Also, thanks to Han and Mark for reviewing!

>> Update the runtime node to initialize and destroy some common data
>> used by multiple functions in northd.
> 
> Hi Mark,
> 
> It looks good overall as an initiate step to employ the inc-proc engine for
> ovn-northd. It is great that it achieves the no-input-change-no-compute
> outcome with this series.
> However, for the en-runtime node it doesn't look right. I understand it is
> only for demonstration purposes and is supposed to evolve, but it may look
> misleading in how would we expand it further for I-P:
> 
> 1) I think the I-P engine should focus on data dependency. Each node should
> define its data (output data computed by the node's run()/change-handlers).
> The en-runtime node defines its own data as lr_list, datapaths and ports,
> but the run() function merely initiates empty data structures that are
> later filled by en-northd, which is wrong. Instead, en-runtime should have
> its own data computed according to its input (all those NB/SB  tables), and
> then en-northd should use en-runtime data  in a read-only fashion. It is
> better not adding this node if we don't have this data dependency defined.
> 
> 2) en-northd run() calls ovn_db_run(), which accesses the inputs (DB
> tables) using the northd_context instead of the data from its input nodes.
> If we really want to use the engine for incremental processing, then I
> think the first step is to make sure we never access data through any
> global context in engine functions, and only use input data from the engine
> nodes it depends on. The engine context should only contain idl_txn for
> writing to DBs (even this could be improved so that we don't have any
> global ctx in engines at all, but at least that's how we are living with in
> ovn-controller). Otherwise it would be hard to ensure correctness of I-P.
> For example, what if in ovn_db_run() it depends on some data from the
> context that is not in any of the input nodes, and now if that data
> changes, the ovn_db_run() won't be triggered any more because engine inputs
> not changed, and this would be a bug.
> 
> Thanks,
> Han
> 
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  northd/en-northd.c  |  9 -
>>  northd/en-runtime.c | 30 --
>>  northd/en-runtime.h |  8 
>>  northd/northd.c | 15 +--
>>  northd/northd.h |  5 -
>>  5 files changed, 53 insertions(+), 14 deletions(-)
>>
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> index d310fa4dd31f..2a3250f3d57a 100644
>> --- a/northd/en-northd.c
>> +++ b/northd/en-northd.c
>> @@ -19,6 +19,7 @@
>>  #include 
>>
>>  #include "en-northd.h"
>> +#include "en-runtime.h"
>>  #include "lib/inc-proc-eng.h"
>>  #include "northd.h"
>>  #include "openvswitch/vlog.h"
>> @@ -29,7 +30,13 @@ void en_northd_run(struct engine_node *node, void
> *data OVS_UNUSED)
>>  {
>>  const struct engine_context *eng_ctx = engine_get_context();
>>  struct northd_context *ctx = eng_ctx->client_ctx;
>> -ovn_db_run(ctx);
>> +
>> +struct ed_type_runtime *runtime_data =
>> + engine_get_input_data("runtime", node);
>> +
>> +ovn_db_run(ctx, _data->lr_list,
>> +_data->datapaths,
>> +_data->ports);
>>
>>  engine_set_node_state(node, EN_UPDATED);
>>
>> diff --git a/northd/en-runtime.c b/northd/en-runtime.c
>> index aac01cd0351f..b8e5766823bf 100644
>> --- a/northd/en-runtime.c
>> +++ b/northd/en-runtime.c
>> @@ -19,7 +19,9 @@
>>  #include 
>>
>>  #include "en-runtime.h"
>> +#include "openvswitch/hmap.h"
>>  #include "lib/inc-proc-eng.h"
>> +#include "openvswitch/list.h"
>>  #include "northd.h"
>>  #include "openvswitch/vlog.h"
>>
>> @@ -27,14 +29,38 @@ VLOG_DEFINE_THIS_MODULE(en_runtime);
>>
>>  void en_runtime_run(struct engine_node *node, void *data OVS_UNUSED)
>>  {
>> +struct ed_type_runtime *runtime_data = data;
>> +
>> +struct ovs_list *lr_list = _data->lr_list;
>> +struct hmap *datapaths = _data->datapaths;
>> +struct hmap *ports = _data->ports;
>> +
>> +destroy_datapaths_and_ports(datapaths, ports, lr_list);
>> +
>> +ovs_list_init(lr_list);
>> +hmap_init(datapaths);
>> +hmap_init(ports);

Re: [ovs-dev] [PATCH ovn v4 7/7] northd: Add functionality to runtime node

2021-09-16 Thread Mark Gray
On 16/09/2021 08:08, Han Zhou wrote:
> On Fri, Sep 3, 2021 at 5:22 AM Mark Gray  wrote:
>>
>> Update the runtime node to initialize and destroy some common data
>> used by multiple functions in northd.
> 
> Hi Mark,
> 
> It looks good overall as an initiate step to employ the inc-proc engine for
> ovn-northd. It is great that it achieves the no-input-change-no-compute
> outcome with this series.
> However, for the en-runtime node it doesn't look right. I understand it is
> only for demonstration purposes and is supposed to evolve, but it may look
> misleading in how would we expand it further for I-P:

Specific comments below. However, I think the rework would be
significant enough that it will be difficult to include before code
freeze. Therefore, if the maintainers are OK with it, I request only
that the first two patches in the series get merged - the ones that
refactor northd in preparation for this. I will continue working on I-P
in the interim. If this is OK, I will send out a v5 that rebases this
series only includes these?

> 
> 1) I think the I-P engine should focus on data dependency. Each node should
> define its data (output data computed by the node's run()/change-handlers).
> The en-runtime node defines its own data as lr_list, datapaths and ports,
> but the run() function merely initiates empty data structures that are
> later filled by en-northd, which is wrong. Instead, en-runtime should have
> its own data computed according to its input (all those NB/SB  tables), and
> then en-northd should use en-runtime data  in a read-only fashion. It is
> better not adding this node if we don't have this data dependency defined.

Yes, I completely agree with this and this was my longer-term intention.
> 
> 2) en-northd run() calls ovn_db_run(), which accesses the inputs (DB
> tables) using the northd_context instead of the data from its input nodes.
> If we really want to use the engine for incremental processing, then I
> think the first step is to make sure we never access data through any
> global context in engine functions, and only use input data from the engine
> nodes it depends on. The engine context should only contain idl_txn for
> writing to DBs (even this could be improved so that we don't have any
> global ctx in engines at all, but at least that's how we are living with in
> ovn-controller). Otherwise it would be hard to ensure correctness of I-P.
> For example, what if in ovn_db_run() it depends on some data from the
> context that is not in any of the input nodes, and now if that data
> changes, the ovn_db_run() won't be triggered any more because engine inputs
> not changed, and this would be a bug.

Yes, I agree with this. I think in the case of this "northd" node, the
northd_context can be initialized by the "northd" node and used by
ovn_db_run as all it really contains are references to the IDL. However,
I will confirm all this.

> 
> Thanks,
> Han
> 
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  northd/en-northd.c  |  9 -
>>  northd/en-runtime.c | 30 --
>>  northd/en-runtime.h |  8 
>>  northd/northd.c | 15 +--
>>  northd/northd.h |  5 -
>>  5 files changed, 53 insertions(+), 14 deletions(-)
>>
>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>> index d310fa4dd31f..2a3250f3d57a 100644
>> --- a/northd/en-northd.c
>> +++ b/northd/en-northd.c
>> @@ -19,6 +19,7 @@
>>  #include 
>>
>>  #include "en-northd.h"
>> +#include "en-runtime.h"
>>  #include "lib/inc-proc-eng.h"
>>  #include "northd.h"
>>  #include "openvswitch/vlog.h"
>> @@ -29,7 +30,13 @@ void en_northd_run(struct engine_node *node, void
> *data OVS_UNUSED)
>>  {
>>  const struct engine_context *eng_ctx = engine_get_context();
>>  struct northd_context *ctx = eng_ctx->client_ctx;
>> -ovn_db_run(ctx);
>> +
>> +struct ed_type_runtime *runtime_data =
>> + engine_get_input_data("runtime", node);
>> +
>> +ovn_db_run(ctx, _data->lr_list,
>> +_data->datapaths,
>> +_data->ports);
>>
>>  engine_set_node_state(node, EN_UPDATED);
>>
>> diff --git a/northd/en-runtime.c b/northd/en-runtime.c
>> index aac01cd0351f..b8e5766823bf 100644
>> --- a/northd/en-runtime.c
>> +++ b/northd/en-runtime.c
>> @@ -19,7 +19,9 @@
>>  #include 
>>
>>  #include "en-runtime.h"
>> +#include "openvswitch/hmap.h"
>>  #include "lib/inc-proc-eng.h"
>> +#include "op

Re: [ovs-dev] [PATCH v3 ovn] controller: add datapath meter capability check

2021-09-16 Thread Mark Gray
On 16/09/2021 14:46, Lorenzo Bianconi wrote:
>> On 16/09/2021 04:42, Mark Michelson wrote:
>>> Hi Lorenzo, I have some comments down below.
>>>
>>
>> Thanks for your changes so far Lorenzo.
> 
> Hi Mark,
> 
> thx for the review
> 
>>
>>> On 9/9/21 7:27 PM, Lorenzo Bianconi wrote:
 Dump datapath meter capabilities before configuring meters in
 ovn-controller

 Signed-off-by: Lorenzo Bianconi 
 ---
 Changes since v2:
 - move meter capability logic in lib/features.c

 Changes since v1:
 - move rconn in ovn-controller to avoid concurrency issues
 ---
   controller/ovn-controller.c |  4 ++
   include/ovn/features.h  |  7 +++
   lib/actions.c   |  3 ++
   lib/automake.mk |  1 +
   lib/features.c  | 89 +
   tests/ovn.at|  4 +-
   6 files changed, 106 insertions(+), 2 deletions(-)

 diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
 index 0031a1035..8c6d4393b 100644
 --- a/controller/ovn-controller.c
 +++ b/controller/ovn-controller.c
 @@ -3523,6 +3523,9 @@ main(int argc, char *argv[])
  ovsrec_server_has_datapath_table(ovs_idl_loop.idl)
  ? _int_dp
  : NULL);
 +if (br_int) {
 +ovs_feature_support_init(br_int);
 +}
   
   /* Enable ACL matching for double tagged traffic. */
   if (ovs_idl_txn) {
 @@ -3898,6 +3901,7 @@ loop_done:
   ovsdb_idl_loop_destroy(_idl_loop);
   ovsdb_idl_loop_destroy(_idl_loop);
   
 +ovs_feature_support_deinit();
   free(ovs_remote);
   service_stop();
   
 diff --git a/include/ovn/features.h b/include/ovn/features.h
 index c35d59b14..4a6d45d88 100644
 --- a/include/ovn/features.h
 +++ b/include/ovn/features.h
 @@ -23,17 +23,24 @@
   /* ovn-controller supported feature names. */
   #define OVN_FEATURE_PORT_UP_NOTIF "port-up-notif"
   
 +struct ovsrec_bridge;
 +struct rconn;
 +
>>>
>>> The forward declaration of rconn is unnecessary here.
>>>
   /* OVS datapath supported features.  Based on availability OVN might 
 generate
* different types of openflows.
*/
   enum ovs_feature_support_bits {
   OVS_CT_ZERO_SNAT_SUPPORT_BIT,
 +OVS_DP_METER_SUPPORT_BIT,
   };
   
   enum ovs_feature_value {
   OVS_CT_ZERO_SNAT_SUPPORT = (1 << OVS_CT_ZERO_SNAT_SUPPORT_BIT),
 +OVS_DP_METER_SUPPORT = (1 << OVS_DP_METER_SUPPORT_BIT),
   };
   
 +void ovs_feature_support_init(const struct ovsrec_bridge *br_int);
 +void ovs_feature_support_deinit(void);
   bool ovs_feature_is_supported(enum ovs_feature_value feature);
   bool ovs_feature_support_update(const struct smap *ovs_capabilities);
   
 diff --git a/lib/actions.c b/lib/actions.c
 index c572e88ae..7cf6be308 100644
 --- a/lib/actions.c
 +++ b/lib/actions.c
 @@ -87,6 +87,9 @@ encode_start_controller_op(enum action_opcode opcode, 
 bool pause,
   oc->max_len = UINT16_MAX;
   oc->reason = OFPR_ACTION;
   oc->pause = pause;
 +if (!ovs_feature_is_supported(OVS_DP_METER_SUPPORT)) {
 +meter_id = NX_CTLR_NO_METER;
 +}
   oc->meter_id = meter_id;
   
   struct action_header ah = { .opcode = htonl(opcode) };
 diff --git a/lib/automake.mk b/lib/automake.mk
 index ddfe33948..9f9f447d5 100644
 --- a/lib/automake.mk
 +++ b/lib/automake.mk
 @@ -2,6 +2,7 @@ lib_LTLIBRARIES += lib/libovn.la
   lib_libovn_la_LDFLAGS = \
   $(OVS_LTINFO) \
   -Wl,--version-script=$(top_builddir)/lib/libovn.sym \
 +$(OVS_LIBDIR)/libopenvswitch.la \
   $(AM_LDFLAGS)
   lib_libovn_la_SOURCES = \
lib/acl-log.c \
 diff --git a/lib/features.c b/lib/features.c
 index fddf4c450..bd7ba79ef 100644
 --- a/lib/features.c
 +++ b/lib/features.c
 @@ -18,7 +18,14 @@
   #include 
   
   #include "lib/util.h"
 +#include "lib/dirs.h"
 +#include "socket-util.h"
 +#include "lib/vswitch-idl.h"
   #include "openvswitch/vlog.h"
 +#include "openvswitch/ofpbuf.h"
 +#include "openvswitch/rconn.h"
 +#include "openvswitch/ofp-msgs.h"
 +#include "openvswitch/ofp-meter.h"
   #include "ovn/features.h"
   
   VLOG_DEFINE_THIS_MODULE(features);
 @@ -40,11 +47,15 @@ static uint32_t supported_ovs_features;
   
   static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
   
 +/* ovs-vswitchd connection. */
 +static struct rconn *swconn;
 +
   static bool
   ovs_feature_is_valid(enum ovs_feature_value feature)
   {
   switch (feature) {
   case OVS_CT_ZERO_SNAT_SUPPORT:

Re: [ovs-dev] [PATCH v2] dpif-netlink: Fix feature negotiation for older kernels

2021-09-16 Thread Mark Gray
On 16/09/2021 09:40, Dumitru Ceara wrote:
> On 9/15/21 5:08 PM, Mark Gray wrote:
>> Older kernels do not reject unsupported features. This can lead
>> to a situation in which 'ovs-vswitchd' believes that a feature is
>> supported when, in fact, it is not.
>>
>> This patch probes for this by attempting to set a known unsupported
>> feature.
>>
>> Reported-by: Dumitru Ceara 
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2004083
>> Suggested-by: Ilya Maximets 
>> Signed-off-by: Mark Gray 
>> ---
> 
> This works for me, for this version:
> 
> Tested-by: Dumitru Ceara 
> 
> I do have a small comment below, thanks!
> 
>>
>> Notes:
>> v2: Fix case raised by Dumitru in which kernel is already configured with
>> unsupported features.
>>
>>  lib/dpif-netlink.c | 72 --
>>  1 file changed, 50 insertions(+), 22 deletions(-)
>>
>> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
>> index 34fc04237333..5f4b60c5a6d6 100644
>> --- a/lib/dpif-netlink.c
>> +++ b/lib/dpif-netlink.c
>> @@ -84,6 +84,8 @@ enum { MAX_PORTS = USHRT_MAX };
>>  #define EPOLLEXCLUSIVE (1u << 28)
>>  #endif
>>  
>> +#define OVS_DP_F_UNSUPPORTED (1 << 31);
>> +
>>  /* This PID is not used by the kernel datapath when using dispatch per CPU,
>>   * but it is required to be set (not zero). */
>>  #define DPIF_NETLINK_PER_CPU_PID UINT32_MAX
>> @@ -382,36 +384,62 @@ dpif_netlink_open(const struct dpif_class *class 
>> OVS_UNUSED, const char *name,
>>  dp_request.cmd = OVS_DP_CMD_SET;
>>  }
>>  
>> -/* The Open vSwitch kernel module has two modes for dispatching upcalls:
>> - * per-vport and per-cpu.
>> - *
>> - * When dispatching upcalls per-vport, the kernel will
>> - * send the upcall via a Netlink socket that has been selected based on 
>> the
>> - * vport that received the packet that is causing the upcall.
>> - *
>> - * When dispatching upcall per-cpu, the kernel will send the upcall via
>> - * a Netlink socket that has been selected based on the cpu that 
>> received
>> - * the packet that is causing the upcall.
>> - *
>> - * First we test to see if the kernel module supports per-cpu 
>> dispatching
>> - * (the preferred method). If it does not support per-cpu dispatching, 
>> we
>> - * fall back to the per-vport dispatch mode.
>> +/* Some older kernels will not reject unknown features. This will cause
>> + * 'ovs-vswitchd' to incorrectly assume a feature is supported. In 
>> order to
>> + * test for that, we attempt to set a feature that we know is not 
>> supported
>> + * by any kernel. If this feature is not rejected, we can assume we are
>> + * running on one of these older kernels.
>>   */
>>  dp_request.user_features |= OVS_DP_F_UNALIGNED;
>> -dp_request.user_features &= ~OVS_DP_F_VPORT_PIDS;
>> -dp_request.user_features |= OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
>> +dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
>> +dp_request.user_features |= OVS_DP_F_UNSUPPORTED;
> 
> Nit: Sorry, I missed this on v1, but I guess we could just remove the
> lines that set OVS_DP_F_UNALIGNED and OVS_DP_F_VPORT_PIDS here, and just
> request OVS_DP_F_UNSUPPORTED.  We set the correct features anyway, in
> all cases, below.

I don't want to do that because it would change the behaviour of the
"create" case. In the previous code, when we are creating the datapath,
we set UNALIGNED, VPORT_PIDs using the NEW command. If I remove that, I
will call NEW without the flags and then SET them flags after. Not sure
if it will have any adverse consequences on some version of the kernel
so it may not be worth the risk. What do you think?

> 
> As far as I can tell this doesn't affect functionality; I tested with
> the two lines removed and it looks OK to me.  If you send a v3 removing
> these two lines please feel free to keep the "tested-by".
> 
>>  error = dpif_netlink_dp_transact(_request, , );
>>  if (error) {
>> -dp_request.user_features &= ~OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
>> +/* The Open vSwitch kernel module has two modes for dispatching
>> + * upcalls: per-vport and per-cpu.
>> + *
>> + * When dispatching upcalls per-vport, the kernel will
>> + * send the upcall via a Netlink socket that has been selected 
>> based on
>> + * the vport that received the packet tha

Re: [ovs-dev] [PATCH] rconn: Add additional coverage counters rconn_run and rconn_retry

2021-09-16 Thread Mark Gray
On 15/09/2021 22:49, Ilya Maximets wrote:
> On 7/29/21 16:22, Mark Gray wrote:
>> Add counters to measure the number of times rconn_run() is
>> executed and the number of times rconn_send() must retry
>> due to an overflow at the vconn layer.
>>
>> These counters allow for more effective debugging of buffer
>> overflows from rconn_send().
>>
>> Signed-off-by: Mark Gray 
>> ---
>>  lib/rconn.c | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/lib/rconn.c b/lib/rconn.c
>> index a96b2eb8bf43..e635a7ff6284 100644
>> --- a/lib/rconn.c
>> +++ b/lib/rconn.c
>> @@ -40,6 +40,8 @@ COVERAGE_DEFINE(rconn_discarded);
>>  COVERAGE_DEFINE(rconn_overflow);
>>  COVERAGE_DEFINE(rconn_queued);
>>  COVERAGE_DEFINE(rconn_sent);
>> +COVERAGE_DEFINE(rconn_run);
>> +COVERAGE_DEFINE(rconn_retry);
>>  
>>  /* The connection states have the following meanings:
>>   *
>> @@ -624,6 +626,8 @@ rconn_run(struct rconn *rc)
>>  int old_state;
>>  size_t i;
>>  
>> +COVERAGE_INC(rconn_run);
> 
> Hi, Mark.  I'm not sure what is a value of counting this?
> rconn_run() supposed to be called unconditionally and it
> doesn't seem very useful to count these calls.
> 
> What do you think?
> 

I needed it because I was trying to understand the ratio of the number
of rconn_retry() calls to the number of rconn_run() calls. I suppose
(depending on how rconn was being used) you may be able determine this
from another counter but it just seemed more convenient like this. If
you think this is not valuable, I can leave it out.

>> +
>>  ovs_mutex_lock(>mutex);
>>  if (rc->vconn) {
>>  int error;
>> @@ -1132,6 +1136,8 @@ try_send(struct rconn *rc)
>>  if (retval != EAGAIN) {
>>  report_error(rc, retval);
>>  disconnect(rc, retval);
>> +} else {
>> +COVERAGE_INC(rconn_retry);
> 
> It might be better to rename to something like 'rconn_send_retry'.

Ok. I will rename this when I get a reply to above.
> 
>>  }
>>  return retval;
>>  }
>>
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] ovn.at: Fix flaky test "controller I-P handling with monitoring disabled".

2021-09-16 Thread Mark Gray
On 15/09/2021 09:52, Xavier Simonart wrote:
> Test was waiting for port to be up in SBDB before checking number of flows

Would this feature prevent this?

5c3371922994 ("if-status: Add OVS interface status management module.")

> in OVS. However, there is no guarantee that all flows are installed
> in OVS when port is up. Test was randomly failing as some flows were
> installed, but not all.
> To fix this, we wait until the last flow (with actions=output) is
> installed.
> Also fixed small typo in logging (for the same test).
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2004390
> Fixes: f8a81693b0 ("ovn-controller: Fix the missing flows with monitor-all 
> set to True")
> Signed-off-by: Xavier Simonart 
> ---
>  tests/ovn.at | 28 ++--
>  1 file changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 30625ec37..18aeacd02 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -23448,6 +23448,12 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
>  
>  wait_for_ports_up sw0-p1
>  
> +# Wait for last flow to be installed
> +OVS_WAIT_UNTIL([
> +test $(as hv1 ovs-ofctl dump-flows br-int | \
> +grep "actions=output" -c) -eq 1
> +])
> +
>  # Get the number of OF flows in hv1 and hv2
>  hv1_offlows=$(as hv1 ovs-ofctl dump-flows br-int | wc -l)
>  echo "hv1 flows : $hv1_offlows"
> @@ -23462,6 +23468,12 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
>  
>  wait_for_ports_up sw0-p2
>  
> +# Wait for last flow to be installed
> +OVS_WAIT_UNTIL([
> +test $(as hv2 ovs-ofctl dump-flows br-int | \
> +grep "actions=output" -c) -eq 1
> +])
> +
>  hv2_offlows=$(as hv2 ovs-ofctl dump-flows br-int | wc -l)
>  echo "hv2 flows : $hv2_offlows"
>  AT_CHECK([test $hv2_offlows -gt 0])
> @@ -23500,9 +23512,15 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
>  
>  wait_for_ports_up sw0-p1
>  
> +# Wait for last flow to be installed
> +OVS_WAIT_UNTIL([
> +test $(as hv1 ovs-ofctl dump-flows br-int | \
> +grep "actions=output" -c) -eq 1
> +])
> +
>  # Get the number of OF flows in hv1 and hv2
>  hv1_offlows_mon=$(as hv1 ovs-ofctl dump-flows br-int | wc -l)
> -echo "hv1 flows after monitor-all=true : $hv1_offlows"
> +echo "hv1 flows after monitor-all=true : $hv1_offlows_mon"
>  AT_CHECK([test "$hv1_offlows" = "$hv1_offlows_mon"])
>  
>  as hv2
> @@ -23514,8 +23532,14 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
>  
>  wait_for_ports_up sw0-p2
>  
> +# Wait for last flow to be installed
> +OVS_WAIT_UNTIL([
> +test $(as hv2 ovs-ofctl dump-flows br-int | \
> +grep "actions=output" -c) -eq 1
> +])
> +
>  hv2_offlows_mon=$(as hv2 ovs-ofctl dump-flows br-int | wc -l)
> -echo "hv2 flows after monitor-all=true : $hv2_offlows"
> +echo "hv2 flows after monitor-all=true : $hv2_offlows_mon"
>  AT_CHECK([test "$hv2_offlows" = "$hv2_offlows_mon"])
>  
>  OVN_CLEANUP([hv1], [hv2])
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v3 ovn] controller: add datapath meter capability check

2021-09-16 Thread Mark Gray
On 16/09/2021 04:42, Mark Michelson wrote:
> Hi Lorenzo, I have some comments down below.
>

Thanks for your changes so far Lorenzo.

> On 9/9/21 7:27 PM, Lorenzo Bianconi wrote:
>> Dump datapath meter capabilities before configuring meters in
>> ovn-controller
>>
>> Signed-off-by: Lorenzo Bianconi 
>> ---
>> Changes since v2:
>> - move meter capability logic in lib/features.c
>>
>> Changes since v1:
>> - move rconn in ovn-controller to avoid concurrency issues
>> ---
>>   controller/ovn-controller.c |  4 ++
>>   include/ovn/features.h  |  7 +++
>>   lib/actions.c   |  3 ++
>>   lib/automake.mk |  1 +
>>   lib/features.c  | 89 +
>>   tests/ovn.at|  4 +-
>>   6 files changed, 106 insertions(+), 2 deletions(-)
>>
>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>> index 0031a1035..8c6d4393b 100644
>> --- a/controller/ovn-controller.c
>> +++ b/controller/ovn-controller.c
>> @@ -3523,6 +3523,9 @@ main(int argc, char *argv[])
>>  ovsrec_server_has_datapath_table(ovs_idl_loop.idl)
>>  ? _int_dp
>>  : NULL);
>> +if (br_int) {
>> +ovs_feature_support_init(br_int);
>> +}
>>   
>>   /* Enable ACL matching for double tagged traffic. */
>>   if (ovs_idl_txn) {
>> @@ -3898,6 +3901,7 @@ loop_done:
>>   ovsdb_idl_loop_destroy(_idl_loop);
>>   ovsdb_idl_loop_destroy(_idl_loop);
>>   
>> +ovs_feature_support_deinit();
>>   free(ovs_remote);
>>   service_stop();
>>   
>> diff --git a/include/ovn/features.h b/include/ovn/features.h
>> index c35d59b14..4a6d45d88 100644
>> --- a/include/ovn/features.h
>> +++ b/include/ovn/features.h
>> @@ -23,17 +23,24 @@
>>   /* ovn-controller supported feature names. */
>>   #define OVN_FEATURE_PORT_UP_NOTIF "port-up-notif"
>>   
>> +struct ovsrec_bridge;
>> +struct rconn;
>> +
> 
> The forward declaration of rconn is unnecessary here.
> 
>>   /* OVS datapath supported features.  Based on availability OVN might 
>> generate
>>* different types of openflows.
>>*/
>>   enum ovs_feature_support_bits {
>>   OVS_CT_ZERO_SNAT_SUPPORT_BIT,
>> +OVS_DP_METER_SUPPORT_BIT,
>>   };
>>   
>>   enum ovs_feature_value {
>>   OVS_CT_ZERO_SNAT_SUPPORT = (1 << OVS_CT_ZERO_SNAT_SUPPORT_BIT),
>> +OVS_DP_METER_SUPPORT = (1 << OVS_DP_METER_SUPPORT_BIT),
>>   };
>>   
>> +void ovs_feature_support_init(const struct ovsrec_bridge *br_int);
>> +void ovs_feature_support_deinit(void);
>>   bool ovs_feature_is_supported(enum ovs_feature_value feature);
>>   bool ovs_feature_support_update(const struct smap *ovs_capabilities);
>>   
>> diff --git a/lib/actions.c b/lib/actions.c
>> index c572e88ae..7cf6be308 100644
>> --- a/lib/actions.c
>> +++ b/lib/actions.c
>> @@ -87,6 +87,9 @@ encode_start_controller_op(enum action_opcode opcode, bool 
>> pause,
>>   oc->max_len = UINT16_MAX;
>>   oc->reason = OFPR_ACTION;
>>   oc->pause = pause;
>> +if (!ovs_feature_is_supported(OVS_DP_METER_SUPPORT)) {
>> +meter_id = NX_CTLR_NO_METER;
>> +}
>>   oc->meter_id = meter_id;
>>   
>>   struct action_header ah = { .opcode = htonl(opcode) };
>> diff --git a/lib/automake.mk b/lib/automake.mk
>> index ddfe33948..9f9f447d5 100644
>> --- a/lib/automake.mk
>> +++ b/lib/automake.mk
>> @@ -2,6 +2,7 @@ lib_LTLIBRARIES += lib/libovn.la
>>   lib_libovn_la_LDFLAGS = \
>>   $(OVS_LTINFO) \
>>   -Wl,--version-script=$(top_builddir)/lib/libovn.sym \
>> +$(OVS_LIBDIR)/libopenvswitch.la \
>>   $(AM_LDFLAGS)
>>   lib_libovn_la_SOURCES = \
>>  lib/acl-log.c \
>> diff --git a/lib/features.c b/lib/features.c
>> index fddf4c450..bd7ba79ef 100644
>> --- a/lib/features.c
>> +++ b/lib/features.c
>> @@ -18,7 +18,14 @@
>>   #include 
>>   
>>   #include "lib/util.h"
>> +#include "lib/dirs.h"
>> +#include "socket-util.h"
>> +#include "lib/vswitch-idl.h"
>>   #include "openvswitch/vlog.h"
>> +#include "openvswitch/ofpbuf.h"
>> +#include "openvswitch/rconn.h"
>> +#include "openvswitch/ofp-msgs.h"
>> +#include "openvswitch/ofp-meter.h"
>>   #include "ovn/features.h"
>>   
>>   VLOG_DEFINE_THIS_MODULE(features);
>> @@ -40,11 +47,15 @@ static uint32_t supported_ovs_features;
>>   
>>   static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
>>   
>> +/* ovs-vswitchd connection. */
>> +static struct rconn *swconn;
>> +
>>   static bool
>>   ovs_feature_is_valid(enum ovs_feature_value feature)
>>   {
>>   switch (feature) {
>>   case OVS_CT_ZERO_SNAT_SUPPORT:
>> +case OVS_DP_METER_SUPPORT:
>>   return true;
>>   default:
>>   return false;
>> @@ -58,6 +69,80 @@ ovs_feature_is_supported(enum ovs_feature_value feature)
>>   return supported_ovs_features & feature;
>>   }
>>   
>> +static bool
>> +ovn_controller_get_ofp_capa(void)
This is definitely a nit, but I think I prefer something 

Re: [ovs-dev] [PATCH ovn v4 0/7] northd: Split northd and northd incremental processing framework

2021-09-15 Thread Mark Gray
Hi,

Dumitru mentioned to me that the impact of change tracking may affect
the performance relative to the current code. I did some quick tests
with a large NBDB and checked northd timings. The results are below. It
doesn't seem to have a significant impact but the data is a bit noisy.

Without this patch:

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test1 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 2:
ovn-northd delay before processing: 7000ms
ovn-northd completion:  14935ms
Statistics for 'ovnnb_db_run'
  Total samples: 5
  Maximum: 7915 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 6732.375000 msec
  Long term average: 7831.435378 msec

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test2 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 3:
ovn-northd delay before processing: 6645ms
ovn-northd completion:  14365ms
Statistics for 'ovnnb_db_run'
  Total samples: 5
  Maximum: 7600 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 6618.25 msec
  Long term average: 7460.322269 msec

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test3 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 4:
ovn-northd delay before processing: 6670ms
ovn-northd completion:  14362ms
Statistics for 'ovnnb_db_run'
  Total samples: 5
  Maximum: 7568 msec
  Minimum: 0 msec
  95th percentile: 0.00 msec
  Short term average: 6615.75 msec
  Long term average: 7476.213026 msec


With this patch:

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test1 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 2:
ovn-northd delay before processing: 112ms
ovn-northd completion:  7986ms
Statistics for 'ovnnb_db_run'
  Total samples: 3
  Maximum: 7732 msec
  Minimum: 7535 msec
  95th percentile: 7535.00 msec
  Short term average: 7620.50 msec
  Long term average: 7729.515200 msec

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test2 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 3:
ovn-northd delay before processing: 118ms
ovn-northd completion:  7826ms
Statistics for 'ovnnb_db_run'
  Total samples: 3
  Maximum: 7564 msec
  Minimum: 7562 msec
  95th percentile: 7562.00 msec
  Short term average: 7563.25 msec
  Long term average: 7563.000100 msec

ovn-appctl -t ovn-northd stopwatch/reset ovnnb_db_run && ovn-nbctl
--print-wait-time --wait=sb lsp-add lswitch-ovn-scale-77 test3 &&
ovn-appctl -t ovn-northd stopwatch/show ovnnb_db_run
Time spent on processing nb_cfg 4:
ovn-northd delay before processing: 109ms
ovn-northd completion:  7880ms
Statistics for 'ovnnb_db_run'
  Total samples: 3
  Maximum: 7767 msec
  Minimum: 7555 msec
  95th percentile: 7555.00 msec
  Short term average: 7623.000000 msec
  Long term average: 7615.904800 msec



On 03/09/2021 13:21, Mark Gray wrote:
> Part 1:
> The first two comits deal with reorganising the northd code base a little.
> Please note that this commit mainly involves moving code around with minimal
> code changes. However, due to tight coupling between ovn-northd.c and 
> northd.c,
> some minor changes were needed. For reference, and to help reviews, please
> examine the following at a minimum:
> 
> * Configuration of the probe interval in northd.c 
> (ovsdb_idl_set_probe_interval())
> * Passing of "use_parallel_build" and "lflow_locks" from ovn-northd.c and
>   northd.c.
> * Update of "struct northd_context": additon of fields and move to h file.
> 
> The commits were (hopefully) structured in a way to make the review easier. As
> this change touches all of ovn-northd, any change to "master" will make a 
> rebase
> necessary and probably difficult. Therefore, if the general ideas is OK, then
> it would be great if this series could be expedited to prevent many rebases!
> 
> Part 2:
> The remaining commits add the inc-proc-eng framework to northd. This does 
> *not*
> add any incremental processing of northd processing at this stage but 
> provides the
> framework. Even in this base configuration, we see an advant

[ovs-dev] [PATCH v2] dpif-netlink: Fix feature negotiation for older kernels

2021-09-15 Thread Mark Gray
Older kernels do not reject unsupported features. This can lead
to a situation in which 'ovs-vswitchd' believes that a feature is
supported when, in fact, it is not.

This patch probes for this by attempting to set a known unsupported
feature.

Reported-by: Dumitru Ceara 
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2004083
Suggested-by: Ilya Maximets 
Signed-off-by: Mark Gray 
---

Notes:
v2: Fix case raised by Dumitru in which kernel is already configured with
unsupported features.

 lib/dpif-netlink.c | 72 --
 1 file changed, 50 insertions(+), 22 deletions(-)

diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 34fc04237333..5f4b60c5a6d6 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -84,6 +84,8 @@ enum { MAX_PORTS = USHRT_MAX };
 #define EPOLLEXCLUSIVE (1u << 28)
 #endif
 
+#define OVS_DP_F_UNSUPPORTED (1 << 31);
+
 /* This PID is not used by the kernel datapath when using dispatch per CPU,
  * but it is required to be set (not zero). */
 #define DPIF_NETLINK_PER_CPU_PID UINT32_MAX
@@ -382,36 +384,62 @@ dpif_netlink_open(const struct dpif_class *class 
OVS_UNUSED, const char *name,
 dp_request.cmd = OVS_DP_CMD_SET;
 }
 
-/* The Open vSwitch kernel module has two modes for dispatching upcalls:
- * per-vport and per-cpu.
- *
- * When dispatching upcalls per-vport, the kernel will
- * send the upcall via a Netlink socket that has been selected based on the
- * vport that received the packet that is causing the upcall.
- *
- * When dispatching upcall per-cpu, the kernel will send the upcall via
- * a Netlink socket that has been selected based on the cpu that received
- * the packet that is causing the upcall.
- *
- * First we test to see if the kernel module supports per-cpu dispatching
- * (the preferred method). If it does not support per-cpu dispatching, we
- * fall back to the per-vport dispatch mode.
+/* Some older kernels will not reject unknown features. This will cause
+ * 'ovs-vswitchd' to incorrectly assume a feature is supported. In order to
+ * test for that, we attempt to set a feature that we know is not supported
+ * by any kernel. If this feature is not rejected, we can assume we are
+ * running on one of these older kernels.
  */
 dp_request.user_features |= OVS_DP_F_UNALIGNED;
-dp_request.user_features &= ~OVS_DP_F_VPORT_PIDS;
-dp_request.user_features |= OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
+dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
+dp_request.user_features |= OVS_DP_F_UNSUPPORTED;
 error = dpif_netlink_dp_transact(_request, , );
 if (error) {
-dp_request.user_features &= ~OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
+/* The Open vSwitch kernel module has two modes for dispatching
+ * upcalls: per-vport and per-cpu.
+ *
+ * When dispatching upcalls per-vport, the kernel will
+ * send the upcall via a Netlink socket that has been selected based on
+ * the vport that received the packet that is causing the upcall.
+ *
+ * When dispatching upcall per-cpu, the kernel will send the upcall via
+ * a Netlink socket that has been selected based on the cpu that
+ * received the packet that is causing the upcall.
+ *
+ * First we test to see if the kernel module supports per-cpu
+ * dispatching (the preferred method). If it does not support per-cpu
+ * dispatching, we fall back to the per-vport dispatch mode.
+ */
+dp_request.user_features &= ~OVS_DP_F_UNSUPPORTED;
+dp_request.user_features |= OVS_DP_F_UNALIGNED;
+dp_request.user_features &= ~OVS_DP_F_VPORT_PIDS;
+dp_request.user_features |= OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
+error = dpif_netlink_dp_transact(_request, , );
+if (error) {
+dp_request.user_features &= ~OVS_DP_F_DISPATCH_UPCALL_PER_CPU;
+dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
+error = dpif_netlink_dp_transact(_request, , );
+}
+if (error) {
+return error;
+}
+
+error = open_dpif(, dpifp);
+dpif_netlink_set_features(*dpifp, OVS_DP_F_TC_RECIRC_SHARING);
+} else {
+VLOG_INFO("Kernel does not correctly support feature negotiation. "
+  "Using standard features.");
+dp_request.cmd = OVS_DP_CMD_SET;
+dp_request.user_features = 0;
+dp_request.user_features |= OVS_DP_F_UNALIGNED;
 dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
 error = dpif_netlink_dp_transact(_request, , );
-}
-if (error) {
-return error;
+if (error) {
+return error;
+}
+error = open_dpif(, dpifp);
 }
 
-error = open_dpif(, dpifp);
-dpif_netlink_set_features(*dpifp,

  1   2   3   4   5   6   7   >